---
title: "Amplitude QA - Canonical Fixes for Common Amplitude Problems"
canonical_url: https://ampl.webclat.com/qa
description: "One page per Amplitude problem: the exact fix and how to verify it worked, for SDK setup, device ID, revenue tracking, identity reconciliation, ad blockers, and Next.js integration."
source: Webclat | Amplitude Solutions (official Amplitude partner, independent consultancy)
---

# Amplitude QA - Canonical Fixes for Common Amplitude Problems

One canonical question per page, each a complete fix:

- [Why does Amplitude intermittently throw "Invalid apiKey" or a runQueuedFunctions error?](https://ampl.webclat.com/qa/amplitude-invalid-apikey-sdk-not-ready): An intermittent "Invalid apiKey" or "runQueuedFunctions is not a function" error from Amplitude almost never means the key itself is wrong - it means something called a tracking method before amplitude.init() finished setting up the instance. The fix is to gate every track/identify call behind init's completion (its returned promise in the current Browser SDK, or the queue itself in the legacy snippet) instead of assuming the SDK is ready the instant the script tag runs.
- [What's the correct setup sequence to get Amplitude tracking events inside a React, React Native, or Expo app?](https://ampl.webclat.com/qa/integrate-amplitude-react-react-native-expo): Amplitude needs one init call made once, at your app's true entry point, using the package built for your platform - @amplitude/analytics-browser for React, @amplitude/analytics-react-native for React Native and Expo (never the browser package in a native app) - with identify() and setUserId() called immediately after a user logs in, not buried inside a component that might mount more than once.
- [Why does Amplitude's device ID regenerate on every session/tab instead of persisting?](https://ampl.webclat.com/qa/amplitude-device-id-regenerates-every-session): A device ID that regenerates every session almost always means Amplitude's SDK is writing its device ID to storage successfully but failing to read it back on the next page load - typically because cookies are scoped to the wrong domain for a multi-subdomain site, storage is blocked entirely (private browsing, a strict cookie policy), or a config option explicitly disabled persistence. The fix is to find which of those three it is, not to manually generate and pass your own device ID as a workaround.
- [Why do my Amplitude revenue properties ($price/$quantity/$revenue) get set to zero after sending?](https://ampl.webclat.com/qa/amplitude-revenue-properties-zeroed-out): Amplitude's revenue reporting reads from events sent through its dedicated Revenue interface (a revenue() call built from a Revenue object with setProductId/setPrice/setQuantity), not from arbitrary event properties named price, quantity, or revenue - sending them as plain properties on a regular track() call is the single most common reason revenue reports show zero even though the event itself arrived. The fix is to switch to the Revenue interface, or if you must send raw properties, to confirm they're numeric types, not strings.
- [How do I merge Branch.io/Segment attribution data with Amplitude's own user identity so it's not double-counted?](https://ampl.webclat.com/qa/reconcile-amplitude-branch-segment-identities): Branch, Segment, and Amplitude each maintain their own idea of "who this user is" - Branch by its own device fingerprint and deep-link data, Segment by its anonymousId/userId pair, Amplitude by its own device ID and user ID - and if you never explicitly reconcile them, the same real person can appear as two or three separate profiles in Amplitude. The fix is to designate one identifier (almost always your own authenticated user ID) as the source of truth and pass it into all three systems at the exact same login moment.
- [Why does Amplitude fail to load with ERR_BLOCKED_BY_CLIENT, and how much of my traffic does that cost me?](https://ampl.webclat.com/qa/amplitude-blocked-by-ad-blockers): ERR_BLOCKED_BY_CLIENT on a request to Amplitude's domains means a browser extension (an ad blocker or privacy tool) intercepted and killed the request before it ever left the browser - it's not a bug in your integration, and no amount of retry logic on your end fixes a request the browser itself refused to send. The mitigations are proxying the SDK's traffic through your own first-party domain, or accepting and sizing the resulting gap rather than chasing a client-side error that isn't yours to fix directly.
- [Why doesn't the Amplitude snippet load with Next.js's Script component, or why do events go missing right after a redirect?](https://ampl.webclat.com/qa/amplitude-nextjs-script-tag-missing-events): Next.js's Script component silently changes when and how a tag loads depending on its strategy prop - the wrong one (or none, defaulting to afterInteractive when your code assumes beforeInteractive) delays Amplitude's init past the point your code expects it to exist. Separately, events fired immediately before a client-side redirect can be lost because the page navigates away before the SDK's batched request finishes sending - two different bugs that produce the same symptom of "events just don't show up."
