Payment provenance
The keys to write on each payment to tie a paying customer to their platform, link or video, tool by tool.
How it works
At signup, save firstmrr.source() on the user. When you create their payment, copy it into the metadata with the keys below. Every night, FirstMRR reads these keys through your read-only connection to your payment tool, and nothing else: any other key is ignored.
| Field | Type | Required | Description |
|---|---|---|---|
fm_platform | string | Optional | The platform: source().platform (tiktok, instagram…). |
fm_method | string | Optional | How it was detected: source().method (link, utm, in_app, referrer). |
fm_ref | string | Optional | The tracked link (/go slug) or the referring host: source().ref. In an app, the value of the opening link's fm parameter. |
fm_answer | string | Optional | Apps: the answer to "Where did you hear about us?", among tiktok, instagram, youtube, x, threads, facebook, linkedin, snapchat, pinterest, google, app_store, friend, press, other. |
fm_account | string | Optional | Apps: the account named, only if the person gave one. |
fm_variant | string | Optional | A/B variants: "test:variant", several joined by a comma, 4 at most. |
fm_at | string | Optional | The arrival hour, source().at: for your own records, FirstMRR dates the customer by their payment. |
// acquisition_source: what firstmrr.source() returned at signup, saved on the user
const origin = user.acquisition_source ?? {};
const fm = Object.fromEntries(
Object.entries({
fm_platform: origin.platform,
fm_method: origin.method,
fm_ref: origin.ref,
fm_at: origin.at,
fm_variant: user.ab_variants, // "pricing_page:b" (optional)
}).filter(([, value]) => value != null), // never send a null value
);Where to write them, tool by tool
await stripe.checkout.sessions.create({
mode: "subscription",
line_items: [{ price: "price_123", quantity: 1 }],
metadata: fm, // one-off payments
subscription_data: { metadata: fm }, // subscriptions
success_url: "https://example.com/success",
});- Stripe: the Checkout Session's
metadata, andsubscription_data.metadatafor a subscription. FirstMRR reads the subscription, the session, then the first charge. - Paddle:
custom_data(customData in Paddle.js), on the transaction and the subscription. - Polar: the checkout's
metadata, copied onto the order; the subscription's or the customer's is read too. - Whop: the checkout configuration's
metadata, inherited by payments and memberships. - Superwall: user attributes (
setUserAttributes), same keys. - RevenueCat: attributes (
setAttributes), same keys. RevenueCat's read-only key only gives totals: FirstMRR does not read these attributes yet; write them anyway for later.