Features
Revenue attribution
Tie every payment back to the visitor, session and campaign that earned it. Connect your payment provider in about two minutes — no code — or use the SDK for full order-level analytics. Both paths are protected against double counting.
Overview
Payments are confirmed on your payment provider's servers — not in the browser. A webhook from Stripe, Lemon Squeezy or Polar is the authoritative record of revenue, but it arrives with no cookies, so on its own FlowGrid can't know which visitor paid. Attribution works by round-tripping two ids through the provider:
- The FlowGrid tracker drops
visitor_idandsession_idcookies as visitors browse. - When you create a checkout, you copy those ids into the provider's metadata.
- The payment webhook carries the metadata back — FlowGrid reads it and joins the revenue to the visitor's full journey: session, landing page, referrer, UTM campaign.
2-minute setup (no code)
FlowGrid hosts the webhook for you — nothing to deploy:
- In the dashboard, open Website settings → Payments and pick your provider.
- Copy the webhook URL shown, e.g.
https://core.flow-grid.xyz/api/v1/attribution/webhook/stripe?web_id=… - Paste it into your provider's dashboard (Stripe: Developers → Webhooks; Lemon Squeezy / Polar: Settings → Webhooks), select the payment events listed in the flow, and save the signing secret back in FlowGrid.
Done — one-time payments and subscription revenue (first payment and every renewal) start flowing into Revenue Attribution, with each paying customer matched to their Flowgrid visitor and visit. Signatures are verified per site with your signing secret. Refunds are not read from this webhook; report them with the SDK path below.
Attribute revenue to a visitor
Without metadata, revenue still records — it just can't be tied to a visitor or campaign. Add two keys when you create the checkout and attribution lights up. If you use the npm SDK server entry:
1import { cookies } from "next/headers";
2import { checkoutAttributionFromCookies } from "flowgrid-sdk/server";
3
4// Stripe
5const session = await stripe.checkout.sessions.create({
6 line_items, mode: "payment", success_url, cancel_url,
7 metadata: { ...checkoutAttributionFromCookies(await cookies()) },
8 // → { flowgrid_visitor_id, flowgrid_session_id }
9});
10
11// Subscriptions (mode: "subscription") need nothing extra: renewals inherit
12// the visitor from this checkout.
13
14// Lemon Squeezy: checkoutData.custom — Polar: metadata (same keys)No SDK? Read the cookies yourself and set the same keys — or, on Stripe only, put the visitor id in client_reference_id:
1// The FlowGrid tracker sets these cookies on your website:
2// visitor_id (365 days) session_id / fg_session_id (~30 min)
3metadata: {
4 flowgrid_visitor_id: readCookie("visitor_id"),
5 flowgrid_session_id: readCookie("session_id") ?? readCookie("fg_session_id"),
6}Client-side checkouts
Creating the checkout in the browser? fg.checkoutAttribution() in the npm SDK returns the same two keys — send them to your checkout endpoint with the price id.
Subscriptions from your own webhook
Payments and refunds always come from the connected provider — there is no SDK call for them. If you also want subscription lifecycle events (start, change, cancel, renew, trials) under your own control for the MRR and churn dashboards, handle your billing webhook and report them with flowgrid-sdk/server, carrying the same attribution ids:
1import { attributionFromMetadata } from "flowgrid-sdk/server";
2import { fg } from "@/lib/flowgrid.server";
3
4// customer.subscription.created
5const { visitorId, sessionId } = attributionFromMetadata(event.data.object);
6
7await fg.trackSubscription(
8 { event: "start", subscriptionId, userId, plan, mrr },
9 { visitorId, sessionId },
10);Every subscription event is documented in Server-Side Tracking.
Client-side auto-detect
The no-code tracker (flowgrid.js) also spots checkout returns on its own: when a visitor lands back on your website with a provider id in the URL (Stripe session_id=cs_…, Lemon Squeezy order_id, Polar checkout_id), it marks the conversion against the visitor immediately — before any webhook arrives. This is a marker, not a revenue record: the amount comes from the webhook, so auto-detect never inflates revenue.
Double-counting protection
The same payment can reach Flowgrid more than once — a provider retrying a webhook delivery, or a checkout-return marker arriving before the webhook. Revenue events with a natural identity are deduplicated at ingestion:
- Connected-provider webhooks once per provider transaction id, however many times the provider retries.
- Subscription start and trial conversion once per
subscriptionId.
Duplicates are acknowledged (not errored), so nothing retries. Recurring events — renewals and plan changes — are never deduplicated.