Verify React Native SDK events

このページはまだあなたの言語に翻訳されていません。 現在取り組んでいますので、後でもう一度確認してください。

An event moves through four stages between your track() call and Amplitude's servers. Verify each stage in order. The first stage where the event looks wrong is where the problem is.

For problems common to every Amplitude SDK, go to SDK troubleshooting and debugging. If behavior changed after an SDK upgrade, check the React Native SDK release notes.

Turn on debug logging

Set logLevel to Debug while you verify. Debug logs include every public method call, the internal state before and after it, each plugin step, and the server response.

ts
amplitude.init("AMPLITUDE_API_KEY", undefined, {
  logLevel: amplitude.Types.LogLevel.Debug,
});

The levels are None (0), Error (1), Warn (2, the default), Verbose (3), and Debug (4). The SDK writes to console, so messages appear in the Metro terminal, in the React Native DevTools console, and in Xcode or Logcat. Each message starts with Amplitude Logger, so filter on that prefix.

Return logLevel to Warn before you ship. Debug output includes event payloads and identifiers.

Check what the SDK captured

With debug logging on, each public call prints a block like this:

text
Amplitude Logger [Debug]: {
  "type": "invoke public method",
  "name": "track",
  "args": ["Sign Up Clicked", { "plan": "starter" }],
  "stacktrace": ["at onPress (SignUpScreen.tsx:42:13)", "..."],
  "time": { "start": "2026-11-05T22:59:41.957Z", "end": "2026-11-05T22:59:41.989Z" },
  "states": {
    "before": { "config.apiKey": "...", "timeline.queue.length": 0 },
    "after": { "config.apiKey": "...", "timeline.queue.length": 0 }
  }
}

For methods that return a promise, such as track(), identify(), and flush(), the SDK prints the block after the promise resolves. A track block therefore appears after the upload attempt.

Confirm three things:

  • The call ran. A track block appears. If not, either your code didn't reach the call or init() never ran on the instance you called. A second instance from createInstance() needs its own init().
  • The arguments are right. args shows the event name and properties exactly as the SDK received them.
  • The SDK was ready. Calls made before init() completes don't fail. They wait in a queue and run after init(), so a call that appears early can still send later.

At this stage you can also read the identity the SDK attaches to every event:

ts
amplitude.getDeviceId(); // "64b29057-7f8c-..."
amplitude.getUserId(); // "user-12345" or undefined
amplitude.getSessionId(); // 1793919426773

Check how plugins transformed the event

After capture, each event passes through the plugin pipeline in a fixed order:

  1. Before plugins (type: "before"): The built-in context plugin adds device_id, user_id, session_id, time, insert_id, library, app_version, and the device fields that trackingOptions allows, such as platform, os_name, device_model, language, and ip. On iOS and Android, the SDK's native module supplies the device fields. The network checker pauses uploads while the device is offline.
  2. Enrichment plugins (type: "enrichment", the default): Your own enrichment plugins run here, in the order you add them.
  3. Destination plugins (type: "destination"): The built-in amplitude destination queues the event for upload.

A before or enrichment plugin that returns null drops the event. To find the plugin responsible for a change or a drop, set logLevel to Verbose or Debug. The SDK then logs each step:

text
Amplitude Logger [Log]: Timeline.apply: Event after before plugin '@amplitude/plugin-context-react-native', event: {...}
Amplitude Logger [Log]: Timeline.apply: Final event before destinations, event: {...}

The Final event before destinations line is the exact event the SDK sends. Compare it with what you expect.

To inspect events in code, for example in an automated test, add a destination plugin that records each event without sending it anywhere:

ts
const captured: amplitude.Types.Event[] = [];

amplitude.add({
  name: "inspect-events",
  type: "destination",
  execute: async (event) => {
    captured.push({ ...event });
    return { event, code: 200, message: "inspected" };
  },
});

Destination plugins receive the event after every before and enrichment plugin has run. Remove the plugin with amplitude.remove("inspect-events") when you're done.

Check what the SDK sent

The SDK uploads events with a POST request from JavaScript fetch:

Requests leave the device flushIntervalMillis (1 second by default) after the first event enters the queue. Each request carries up to flushQueueSize (30 by default) events. To send right away, call await amplitude.flush().promise.

To inspect the request itself, use one of these tools:

  • The Network panel in React Native DevTools, which lists fetch requests from JavaScript.
  • A local HTTP proxy, such as Charles or Proxyman, with the device or simulator configured to use it.
  • A custom transportProvider that logs the URL and payload before it sends.
  • For react-native-web, the browser Network tab.

The request body has this shape:

json
{
  "api_key": "AMPLITUDE_API_KEY",
  "events": [
    {
      "event_type": "Sign Up Clicked",
      "event_properties": { "plan": "starter" },
      "device_id": "64b29057-7f8c-...",
      "session_id": 1793919426773,
      "time": 1793919426774,
      "event_id": 1,
      "insert_id": "f393d9ad-...",
      "app_version": "1.0.0",
      "platform": "iOS",
      "os_name": "ios",
      "os_version": "17.0",
      "device_manufacturer": "Apple",
      "device_model": "iPhone15,2",
      "language": "en-US",
      "ip": "$remote",
      "library": "amplitude-react-native-ts/1.13.1"
    }
  ],
  "options": {},
  "client_upload_time": "2026-11-05T22:59:41.990Z"
}

"ip": "$remote" tells Amplitude to use the request's IP address. Set trackingOptions.ipAddress to false to omit it. When you set minIdLength, options carries it as min_id_length.

Compressed request bodies

For Amplitude's own endpoints, the SDK gzip-compresses larger request bodies only when the JavaScript runtime provides CompressionStream. Hermes doesn't, so requests from iOS and Android apps are plain JSON. On react-native-web, compressed requests carry a Content-Encoding: gzip header, and the Network tab shows binary data. To read those events, use the Final event before destinations log line or an inspection plugin instead.

If no request appears:

Check what Amplitude received

Read the upload result

Every tracking method returns { promise }. The promise resolves to a Result after the upload attempt finishes:

ts
const { event, code, message } =
  await amplitude.track("Sign Up Clicked").promise;

event is the final event as sent. code and message come from the server response or from the SDK:

A successful response body looks like this:

json
{
  "code": 200,
  "events_ingested": 1,
  "payload_size_bytes": 412,
  "server_upload_time": 1793919426800
}

A 200 response means Amplitude's ingestion API accepted the event. Amplitude can still exclude an accepted event from analysis later, for example when a block filter matches it.

Manual flushes don't retry

amplitude.flush() sends every queued event once and doesn't retry failures. Each event's promise resolves with the response status and body as the message, for example invalid: {"error": "Invalid API key: ..."}. Scheduled uploads retry and use the messages in the table.

Find the event in Amplitude

  1. Open User Lookup and search for the event's user_id, or its device_id if the user is anonymous.
  2. Select the Activity tab and turn on Live event updates.
  3. Open the event and compare its properties with the Final event before destinations log line.

For events from many users, use the Ingestion Debugger to review accepted and rejected requests for the project. Amplitude's chart queries can take a few minutes longer to include new events than User Lookup does.

これは役に立ちましたか?

For AI agents: a documentation index is available at /docs/llms.txt. Append .md to any page URL for markdown, or send Accept: text/markdown.

このページでは