TrackingSales to visits

Tracking

Trace each sale to its visit

How odo credits each sale to the visit that brought it: Stripe metadata, checkout links tagged for you, Shopify, Paddle and more, and first or last touch.

On this page

When a payment source and a website share a project, odo traces each sale to the visitor who made it and credits the visit that brought them. Every channel, campaign, page and country then shows revenue, and you see revenue per visitor, conversion rate, and the time from a first visit to a first payment.

How it works#

The script keeps one id per visitor, odo_vid. Your checkout passes it to the payment platform, the platform keeps it on the sale, and odo reads it back. odo never guesses: a sale without a visitor shows as not traced.

The sale is credited to the visitor’s last touch by default: their most recent visit that came from somewhere other than Direct. Switch to first touch, the visit that first brought them, with Credit on the Revenue card.

What each platform needs#

Each platform carries the visitor its own documented way, and the script tags checkout links on your pages for you.

PlatformHow the visitor travelsWhat you do
StripeA Payment Link’s client_reference_id, or odo_visitor_id in metadataNothing for Payment Links; pass it from your own checkout (below)
Lemon Squeezycheckout[custom][odo_visitor_id], sent back in its webhooksTurn on instant updates, with a signing secret
PolarCheckout links’ reference_id, kept in the order’s metadataNothing for checkout links; API checkouts pass metadata.odo_visitor_id
Paddlecustom_data.odo_visitor_id on the transactionNothing for paddle_button launchers; Paddle.Checkout.open() passes customData
GumroadA parameter on the product link, sent back in its PingTurn on instant updates (the Ping)
Dodo PaymentsPayment links’ metadata_odo_visitor_idNothing for payment links; API checkouts pass metadata.odo_visitor_id
ShopifyThe cart attribute odo_visitor_idOne line in your theme (shown in its setup); cart permalinks are tagged
WooCommerceThe order meta _odo_visitor_idOne snippet in functions.php (shown in its setup)

The script only touches links on these platforms’ own checkout addresses, adds one parameter, and never one a link already has.

Stripe, from your own checkout#

For Checkout Sessions or PaymentIntents your server makes, pass the visitor into metadata.odo_visitor_id. On your server it’s the odo_vid cookie:

JavaScript
// Server: pass the visitor to Stripe Checkout
const session = await stripe.checkout.sessions.create({
  // …your line items, mode and URLs
  metadata: { odo_visitor_id: req.cookies.odo_vid },
});

In the browser it’s window.odo.visitorId, for a checkout that starts there:

JavaScript
fetch('/checkout', { method: 'POST', body: JSON.stringify({ odo: window.odo?.visitorId }) });

PaymentIntents, Customers and Subscriptions work the same way, with metadata.odo_visitor_id. For odo to read it back, a restricted key needs read access to Charges, Customers, Invoices, Subscriptions and Checkout Sessions; the Sales from visits card says when it’s missing.

After each Stripe sync, odo looks up the new payments, newest first, and refunds follow their payment. Other platforms keep the visitor on the sale itself, so their sales are matched right after each sync, and one whose visitor odo hasn’t seen yet is tried again for three days.

Anything else#

Send the purchase from the page:

JavaScript
odo('Purchase', { revenue: 49, currency: 'USD' })

or from your server, with a project key and the buyer’s odo_vid as visitor. Both are self-reported.

One sale, one credit#

  • A sale traced through a Verified source keeps its seal. Gumroad’s unsigned Ping, a Lemon Squeezy webhook without a signing secret, WooCommerce and test-mode sources are traced too, but never shown as verified.
  • Refunds and disputes take back from the visits their payment was credited to.
  • When a platform traces a sale your page also reported with odo('Purchase') (the same visitor and currency, about the same amount, within two hours), the platform’s replaces the page’s.
  • Cookieless sites, and browsers that send Global Privacy Control, have no visitor id to pass on, so their sales can’t be traced.

Who paid#

For a Stripe sale traced to a visit, odo keeps the buyer’s name, or their email when Stripe has no name, as your Stripe knows them, so your dashboard (and your own AI assistant, which sees what you see) can say who paid. Shared views and the REST API never show it. No other platform’s buyer is kept, and a Stripe sale that isn’t traced keeps none.

This page as markdownllms.txt