Skip to main content

Tracking events

FounderPass surfaces analytics — most-viewed deals, claim conversion, partner-level metrics — but only on the events your integration sends. There are two ways to send them:

  • Client-sidePOST /events/track, called from the end-user surface (hosted app, iframe, browser). No Bearer token; attribution comes from a Firebase token if present, otherwise a session_id.
  • Server-sidePOST /v1/events/track, called from your backend with your Partner JWT. Attributes the event to one of your users without Firebase, resolving them by user_id, email, or external_user_id. See Server-side attribution below.

Client-side tracking

Hook a single POST /events/track call into the key moments of the user journey: listing impressions, detail views, instructions views, promo-code copies, and redemptions.

:::info Partner context, not the API JWT POST /events/track is called from the end-user surface (your hosted app, embed iframe, or API client), not from your backend. Send it to your hosted or sandbox subdomain so the API can identify the partner — no Bearer token required. If the request carries a valid Firebase ID token, the event is attributed to that user; otherwise a stable session_id is the only attribution. To attribute server-side without Firebase, use POST /v1/events/track instead. :::

Sending an event

curl -X POST https://<your-slug>.perks.founderpass.com/events/track \
-H "Content-Type: application/json" \
-d '{
"event_type": "deal_detail_viewed",
"deal_id": "018e4b2a-0000-7def-abcd-000000000010",
"session_id": "sess_abc123",
"source": "hosted_app",
"metadata": { "referrer": "homepage" }
}'

Success returns 200 { "status": "tracked" }.

FieldTypeRequiredNotes
event_typeenumYesSee list below
session_idstringYesA stable per-session ID you generate client-side
sourceenumYeshosted_app or iframe. api is reserved for the server-side endpoint and is rejected here with 400.
deal_iduuidNoRequired for deal-scoped events
user_iduuidNoIgnored — server attributes from the Firebase token if present, never from the body
metadataobjectNoFree-form JSON for your own attribution

:::warning Don't try to spoof user_id The server discards user_id from the request body on this public endpoint. Authenticated attribution only happens when the request carries a valid Firebase ID token. For anonymous events, lean on session_id. To attribute an event to a user from your backend (no Firebase), use the server-side endpoint. :::

Event types

ValueWhen to fire
deal_list_viewedA deal listing page rendered for the user
deal_detail_viewedUser opened the deal detail page
instructions_viewedUser opened the redemption instructions
redeem_url_clickedUser clicked the redeem CTA
promo_code_copiedUser copied the promo code
unique_code_claimedUser claimed a one-time code
deal_redeemedUser completed redemption
upgrade_cta_clickedUser clicked a tier-upgrade CTA
deal_inquiry_submittedUser filled the "request access" form

:::tip deal_redeemed is emitted for you on the API path When you fetch redemption instructions via GET /v1/deals/{id}/instructions?user_id=…, the server auto-emits a deal_redeemed event for that user — once per (partner, user, deal). You don't need to send deal_redeemed yourself for API-driven redemptions; doing so is a no-op for the count. :::

Server-side attribution

POST /v1/events/track records an event from your backend and attributes it to one of your users — no Firebase token required. Authenticate with your Partner JWT (Bearer token), and identify the user with exactly one of user_id, email, or external_user_id (tried in that order; the first present wins). The resolved user must belong to your partner.

curl -X POST https://perks.founderpass.com/v1/events/track \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"event_type": "deal_detail_viewed",
"external_user_id": "cust_abc123",
"deal_id": "018e4b2a-0000-7def-abcd-000000000010",
"metadata": { "surface": "members-dashboard" }
}'

Success returns 200 { "status": "tracked", "user_id": "…" }.

FieldTypeRequiredNotes
event_typeenumYesSame event types as the public endpoint
user_iduuidOne of these threeA FounderPass user ID
emailstringOne of these threeThe user's email, scoped to your partner
external_user_idstringOne of these threeThe ID you set on the user via Syncing users
deal_iduuidFor deal_redeemed, yesValidated against your visible catalogue; required for deal_redeemed
session_id, metadatastring / objectNoCarried through onto the recorded event

The event is always recorded with source = "api". Resolution rules:

  • If none of user_id / email / external_user_id is supplied → 400.
  • If the identifier resolves to no user in your partner → 404.
  • A deal_id outside your visible catalogue (hidden, api_excluded, wrong tenant) → 404.
  • A deal_redeemed is deduplicated to one row per (partner, user, deal), so retries are safe.

Reading analytics back

This endpoint requires a Partner JWT — call it from your backend, not from the browser.

curl "https://perks.founderpass.com/v1/analytics?days=30" \
-H "Authorization: Bearer $TOKEN"

days is a lookback window (1–365, default 30).

Response

{
"total_users": 1240,
"active_users": 312,
"total_deal_views": 5821,
"total_redemptions": 184,
"upgrade_cta_clicks": 27,
"top_deals": [
{ "deal_id": "...", "product_name": "Notion", "views": 312, "redemptions": 41 }
],
"event_counts": {
"deal_list_viewed": 9201,
"deal_detail_viewed": 5821,
"deal_redeemed": 184
}
}

For per-deal time series or CSV export, use the corresponding admin/portal endpoints in the API Reference.