docs
Documentation menu

Amplitude & Mixpanel

Where the analytics integrations stand today.

#Amplitude — Event Streaming (push)

Amplitude pushes events to Pushlane in real time using its Webhook Event Streaming destination. Pushlane exposes a dedicated endpoint that accepts the raw Amplitude batch payload and maps it into the same ingest pipeline as the SDK — including deduplication, catalogue auto-discovery, and flow triggers.

Heads up
Webhook Event Streaming destinations require an Amplitude Growth or Enterprise plan. Starter and Plus plans do not include this feature.

#Amplitude — Setup

In your Amplitude workspace, go to Data → Destinations → Event Streaming, add a new Webhook destination, and configure it as shown below. The Authorization header is the custom header Amplitude lets you attach; set its value to Bearer lpk_live_… — your publishable write-key, found under Settings → API.

text
# In Amplitude: Data → Destinations → Event Streaming → Webhook
# 1. Endpoint URL:
POST https://ingest.pushlane.io/v1/integrations/amplitude

# 2. Custom header (Authentication):
Authorization: Bearer lpk_live_…
Note
Pushlane derives your workspace from the write-key server-side; no tenantId query parameter is needed. A missing or unknown key is rejected with 401 before any event is processed.

#Amplitude — Field mapping

Pushlane maps each Amplitude event object to its normalized form. The mapping is tolerant: the worker also accepts a bare array, a single event object, or an envelope with an events or data key.

Amplitude fieldPushlane fieldNotes
event_typenameRequired — events without a name are skipped
user_idexternalId[object Object] fallback when user_id is absent
timetsEpoch ms (number) or ISO-8601 string; falls back to now
event_propertiespropertiesForwarded as-is
insert_iddedup keyStable hash of name|user|time when absent
Heads up
Events with neither user_id nor device_id cannot be attributed to a user and are skipped — they are counted in the skipped field of the response, never a batch failure.

#Amplitude — Response and limits

The endpoint always returns 200 for a valid authenticated request, even when some events are skipped. It returns 413 when a single request carries more than 500 events.

json
// Success — all or part of the batch accepted
{
  "received": 42,   // events extracted from the payload
  "accepted": 41,   // forwarded into the pipeline (after dedup)
  "skipped": 1      // no user_id / device_id — counted, not failed
}

// Too many events in one request (> 500)
HTTP 413
{ "error": "too_many_events", "max": 500, "received": 512 }

#Mixpanel — Raw Export polling (pull)

Unlike Amplitude, Mixpanel has no real-time per-event outbound webhook. Pushlane pulls your event stream by polling the Mixpanel Raw Export API every 10 minutes using a service account. The Raw Export API is available on all Mixpanel plans.

#Mixpanel — Setup

Go to Settings → Integrations → Mixpanel and click Connect Mixpanel. Fill in the three fields and select your data residency region.

FieldWhere to find it
Service account usernameMixpanel Organization Settings → Service Accounts → create or copy the username
Service account secretGenerated alongside the username — write-only, never displayed after saving
Project IDMixpanel Project Settings → Project ID (numeric)
RegionUS (data.mixpanel.com) or EU (data-eu.mixpanel.com) — must match your project's data residency
Note
The service account secret is encrypted at rest with AES-256-GCM and is never returned to the browser after saving. Only the username, project ID, and region are displayed once configured.

#Mixpanel — How polling works

Every 10 minutes Pushlane fetches events for each connected Mixpanel project:

  • The fetch window runs from the last cursor position to now minus 10 minutes (a lag margin for in-transit events), and is clamped to the last 24 hours.
  • A maximum of 5 000 events per tick are ingested per tenant. When more exist in the window, the oldest are ingested first and the cursor advances to the last ingested event so the next tick resumes from there.
  • Pushlane deduplicates on Mixpanel's $insert_id property (mapped to a deterministic UUID). Window overlaps between ticks are absorbed by the dedup layer — no event is ingested twice regardless of how much the windows overlap.
json
// Mixpanel Raw Export row → Pushlane event
{
  "event":      "Sign Up",        // → name
  "properties": {
    "distinct_id":  "user_abc",   // → externalId
    "time":         1719878400,   // → ts (epoch SECONDS, converted to ms)
    "$insert_id":   "evt_xyz",    // → dedup key (else name|distinct_id|ts)
    "plan":         "pro"         // → forwarded as-is in properties
    // "time", "distinct_id", "$insert_id" are lifted out and NOT forwarded
  }
}

#Mixpanel — Status

The integration card in Settings shows the current sync status:

StatusMeaning
Pending first syncCredentials saved; the first poll has not run yet (runs within 10 minutes)
SyncingLast poll succeeded; events are flowing
Auth failedMixpanel returned 401 or 403 — the service account secret may have expired; reconnect with updated credentials
Heads up
An auth_failed status stops polling for that project until you reconnect with valid credentials. Other transient errors (network, 5xx) are retried on the next tick without changing the status.

#Events in Pushlane

Events imported from both Amplitude and Mixpanel enter the same ingest pipeline as events sent via the SDK or HTTP API. This means:

  • Deduplication (R2) prevents double-counting across batches and retries.
  • Each new event name is auto-discovered in the event catalogue and appears immediately in the flow builder trigger picker.
  • Flows can trigger on any imported event name — for example a segment trigger on Sign Up from Mixpanel works identically to one on an SDK-sent Sign Up.

#Prefer real-time? Mirror analytics into Pushlane.track

The connectors above stream your events into Pushlane server-to-server (push for Amplitude, a 10-minute poll for Mixpanel). If you also want events straight from the app — with no lag, and to instrument new events — mirror your existing analytics.track / logEvent calls into Pushlane.track additively: keep your analytics, and add a Pushlane.track alongside.

typescript
// keep your existing analytics call, add Pushlane.track alongside it
analytics.track('paywall_viewed', { placement: 'home' });
Pushlane.track('paywall_viewed', { placement: 'home' });
Heads up
Reconcile names against your catalogue, rename reserved names (e.g. message_sentchat_message_sent — Pushlane writes message_sent itself), and skip auto-emitted app_open / session_started (the SDK already emits them). The Pushlane MCP's plan_instrumentation tool does this reconciliation automatically — see Events & catalogue for the full rules.

Next: RevenueCat — connect subscription events to flow triggers.