<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:base="https://traffic.cx/">
  <id>https://traffic.cx/blog</id>
  <title>traffic.cx blog</title>
  <subtitle>Tested guides for connecting your marketing to revenue.</subtitle>
  <link rel="alternate" type="text/html" href="https://traffic.cx/blog"/>
  <link rel="self" type="application/atom+xml" href="https://traffic.cx/blog/feed.xml"/>
  <updated>2026-10-22T00:00:00.000Z</updated>
  <author><name>traffic.cx</name></author>
  <entry>
    <id>https://traffic.cx/blog/revenue-attribution-for-saas</id>
    <title>Revenue attribution for SaaS: which traffic actually pays</title>
    <link rel="alternate" type="text/html" href="https://traffic.cx/blog/revenue-attribution-for-saas"/>
    <published>2026-10-22T00:00:00.000Z</published>
    <updated>2026-10-22T00:00:00.000Z</updated>
    <author><name>Karthick</name></author>
    <category term="revenue-attribution" label="Revenue attribution"/>
    <category term="saas" label="SaaS"/>
    <category term="stripe" label="Stripe"/>
    <summary>Tie Stripe, Lemon Squeezy, Polar or Dodo payments to the traffic that earned them, pick an attribution model, and know which numbers to trust.</summary>
    <content type="html">&#60;p&#62;Revenue attribution credits each payment to the marketing source, campaign or page that brought the customer. You see revenue by channel instead of visits by channel. For a SaaS, that means connecting your analytics to your payment provider and deciding which visit gets the credit.&#60;/p&#62;
&#60;h2 id=&#34;what-is-revenue-attribution&#34; tabindex=&#34;-1&#34;&#62;What is revenue attribution?&#60;/h2&#62;&#60;p&#62;Revenue attribution, sometimes called SaaS marketing attribution when it&#38;#39;s applied to subscriptions, answers one question: which traffic paid you? It joins two records that normally live apart: the visit (where someone came from) and the payment (what they paid).&#60;/p&#62;
&#60;h3 id=&#34;revenue-attribution-vs-traffic-analytics-vs-product-analytics&#34; tabindex=&#34;-1&#34;&#62;Revenue attribution vs traffic analytics vs product analytics&#60;/h3&#62;&#60;ul&#62;
&#60;li&#62;&#60;strong&#62;Traffic analytics&#60;/strong&#62; counts visits: sources, pages, campaigns, countries. It tells you what brings people in.&#60;/li&#62;
&#60;li&#62;&#60;strong&#62;Product analytics&#60;/strong&#62; follows signed-in users inside your app: feature use, retention, activation.&#60;/li&#62;
&#60;li&#62;&#60;strong&#62;Revenue attribution&#60;/strong&#62; sits between them. It takes the payment and traces it back to the visit that started the journey.&#60;/li&#62;
&#60;/ul&#62;
&#60;p&#62;A channel can send lots of visitors and no customers. Revenue attribution shows that.&#60;/p&#62;
&#60;h3 id=&#34;why-saas-is-harder&#34; tabindex=&#34;-1&#34;&#62;Why SaaS is harder&#60;/h3&#62;&#60;p&#62;A shop sale usually happens in one visit. SaaS purchases rarely do:&#60;/p&#62;
&#60;ul&#62;
&#60;li&#62;&#60;strong&#62;Trials and delays.&#60;/strong&#62; People sign up, try the product and pay days or weeks later.&#60;/li&#62;
&#60;li&#62;&#60;strong&#62;Renewals.&#60;/strong&#62; Most revenue arrives months after the first visit, with no visit attached.&#60;/li&#62;
&#60;li&#62;&#60;strong&#62;Refunds.&#60;/strong&#62; A payment can be partly or fully reversed later.&#60;/li&#62;
&#60;li&#62;&#60;strong&#62;Several devices.&#60;/strong&#62; Someone reads your blog on their phone and buys on their laptop.&#60;/li&#62;
&#60;/ul&#62;
&#60;p&#62;Each breaks the simple &#38;quot;visit then purchase&#38;quot; link.&#60;/p&#62;
&#60;h2 id=&#34;why-your-analytics-and-stripe-don-t-agree&#34; tabindex=&#34;-1&#34;&#62;Why your analytics and Stripe don&#38;#39;t agree&#60;/h2&#62;&#60;p&#62;Your analytics tool knows sources but not payments. Your billing tool knows payments but not sources. One founder described it on Hacker News:&#60;/p&#62;
&#60;blockquote&#62;
&#60;p&#62;&#38;quot;We&#38;#39;re living in this unfortunate split where tools like Google Analytics tell you where people came from, and Stripe tells you who paid, but there&#38;#39;s no simple way to connect the two.&#38;quot; (&#60;a href=&#34;https://news.ycombinator.com/item?id=44756020&#34;&#62;Lrodd, HN&#60;/a&#62;)&#60;/p&#62;
&#60;/blockquote&#62;
&#60;p&#62;The same post adds: &#38;quot;UTMs and custom attribution params get lost after signup. Stripe doesn&#38;#39;t track attribution.&#38;quot;&#60;/p&#62;
&#60;p&#62;There&#38;#39;s a second problem: &#38;quot;direct&#38;quot; inflation. A customer finds you through a Reddit thread, comes back two weeks later by typing your URL, and pays. A tool that credits the last visit says &#38;quot;Direct&#38;quot;. The Reddit thread that did the work gets nothing.&#60;/p&#62;
&#60;h2 id=&#34;how-revenue-attribution-works-step-by-step&#34; tabindex=&#34;-1&#34;&#62;How revenue attribution works, step by step&#60;/h2&#62;&#60;h3 id=&#34;1-capture-the-visit&#34; tabindex=&#34;-1&#34;&#62;1. Capture the visit&#60;/h3&#62;&#60;p&#62;Record where each visit came from: referrer, UTM tags (&#60;code&#62;utm_source&#60;/code&#62;, &#60;code&#62;utm_medium&#60;/code&#62;, &#60;code&#62;utm_campaign&#60;/code&#62;) and landing page. Tag your own links consistently. &#60;code&#62;Newsletter&#60;/code&#62; and &#60;code&#62;newsletter&#60;/code&#62; become two rows in most tools, so pick lowercase names and keep a list. Never put an email address or customer ID in a UTM tag; links get shared and logged.&#60;/p&#62;
&#60;h3 id=&#34;2-carry-an-identifier-into-checkout&#34; tabindex=&#34;-1&#34;&#62;2. Carry an identifier into checkout&#60;/h3&#62;&#60;p&#62;The payment provider doesn&#38;#39;t know which visit started checkout. You have to tell it. When the visitor starts checkout, read an identifier in the browser (a visit ID, or the UTM values themselves) and pass it to your server. Your server adds it to the checkout&#38;#39;s metadata.&#60;/p&#62;
&#60;p&#62;Do this when checkout starts, not on the thank-you page, which may belong to a later visit.&#60;/p&#62;
&#60;h3 id=&#34;3-match-the-payment-to-the-visit&#34; tabindex=&#34;-1&#34;&#62;3. Match the payment to the visit&#60;/h3&#62;&#60;p&#62;When the payment succeeds, the provider sends a webhook. The payment carries the metadata you added. Your system, or your tool, looks up the visit by that identifier.&#60;/p&#62;
&#60;h3 id=&#34;4-credit-a-source-under-a-model-and-lookback-window&#34; tabindex=&#34;-1&#34;&#62;4. Credit a source under a model and lookback window&#60;/h3&#62;&#60;p&#62;If the customer visited more than once, a &#60;strong&#62;model&#60;/strong&#62; decides which visit gets credit. A &#60;strong&#62;lookback window&#60;/strong&#62; decides how far back to look. Both should be explicit settings, not hidden defaults.&#60;/p&#62;
&#60;h3 id=&#34;5-handle-renewals-refunds-and-payments-you-can-t-match&#34; tabindex=&#34;-1&#34;&#62;5. Handle renewals, refunds and payments you can&#38;#39;t match&#60;/h3&#62;&#60;ul&#62;
&#60;li&#62;&#60;strong&#62;Renewals:&#60;/strong&#62; credit them to the source that won the customer. The renewal was earned by whatever brought them in.&#60;/li&#62;
&#60;li&#62;&#60;strong&#62;Refunds:&#60;/strong&#62; subtract them, and credit them against the original payment&#38;#39;s source.&#60;/li&#62;
&#60;li&#62;&#60;strong&#62;No match:&#60;/strong&#62; keep the payment in your totals as &#38;quot;unattributed&#38;quot;. Don&#38;#39;t assign a guess.&#60;/li&#62;
&#60;/ul&#62;
&#60;h2 id=&#34;attribution-models-for-small-saas&#34; tabindex=&#34;-1&#34;&#62;Attribution models for small SaaS&#60;/h2&#62;&#60;p&#62;An attribution model is the rule that decides which visit gets credit when a customer visited more than once.&#60;/p&#62;
&#60;h3 id=&#34;last-non-direct&#34; tabindex=&#34;-1&#34;&#62;Last non-direct&#60;/h3&#62;&#60;p&#62;Credit the most recent visit before the payment that didn&#38;#39;t come straight in (typed URL or bookmark). If every visit was direct, the payment counts as Direct.&#60;/p&#62;
&#60;p&#62;This fixes the &#38;quot;direct&#38;quot; inflation problem. It shows you what closes sales.&#60;/p&#62;
&#60;h3 id=&#34;first-touch&#34; tabindex=&#34;-1&#34;&#62;First touch&#60;/h3&#62;&#60;p&#62;Credit the earliest visit in the lookback window. This shows you what finds customers in the first place. It&#38;#39;s useful for judging content and SEO, which often start journeys but rarely finish them.&#60;/p&#62;
&#60;h3 id=&#34;multi-touch-models&#34; tabindex=&#34;-1&#34;&#62;Multi-touch models&#60;/h3&#62;&#60;p&#62;Linear models split credit evenly across visits. Time-decay models give more to recent visits. Position-based models weight the first and last.&#60;/p&#62;
&#60;p&#62;They pay off with many paid channels and enough data to trust small differences. Most small SaaS teams aren&#38;#39;t there yet; two simple models compared side by side teach more.&#60;/p&#62;
&#60;h3 id=&#34;choosing-a-lookback-window&#34; tabindex=&#34;-1&#34;&#62;Choosing a lookback window&#60;/h3&#62;&#60;p&#62;The window should cover your normal time from first visit to first payment. If most customers pay within a week of signing up, 30 days is plenty. If buyers research for months, go longer. Too short, and early sources lose credit. Too long, and an old visit gets credit for a sale it had little to do with.&#60;/p&#62;
&#60;p&#62;Check how long your trials take to convert and set the window a bit beyond that. A window longer than the checkout visit only helps if earlier visits are linked to the buyer by a stored identifier, such as a first-party cookie.&#60;/p&#62;
&#60;h3 id=&#34;worked-example-one-customer-three-visits-two-models&#34; tabindex=&#34;-1&#34;&#62;Worked example: one customer, three visits, two models&#60;/h3&#62;&#60;p&#62;&#60;em&#62;This is an illustrative example with made-up numbers, not customer data.&#60;/em&#62;&#60;/p&#62;
&#60;p&#62;A customer makes three visits before subscribing at $29 a month:&#60;/p&#62;
&#60;div class=&#34;docs-table&#34; tabindex=&#34;0&#34; role=&#34;region&#34; aria-label=&#34;Reference table&#34;&#62;&#60;table&#62;&#60;thead&#62;&#60;tr&#62;&#60;th scope=&#34;col&#34;&#62;Visit&#60;/th&#62;&#60;th scope=&#34;col&#34;&#62;When&#60;/th&#62;&#60;th scope=&#34;col&#34;&#62;Source&#60;/th&#62;&#60;/tr&#62;&#60;/thead&#62;&#60;tbody&#62;&#60;tr&#62;&#60;td&#62;1&#60;/td&#62;&#60;td&#62;Day 1&#60;/td&#62;&#60;td&#62;Google organic search, lands on a blog post&#60;/td&#62;&#60;/tr&#62;&#60;tr&#62;&#60;td&#62;2&#60;/td&#62;&#60;td&#62;Day 12&#60;/td&#62;&#60;td&#62;Your newsletter (&#60;code&#62;utm_source=newsletter&#60;/code&#62;)&#60;/td&#62;&#60;/tr&#62;&#60;tr&#62;&#60;td&#62;3&#60;/td&#62;&#60;td&#62;Day 15&#60;/td&#62;&#60;td&#62;Types your URL, starts checkout, pays $29&#60;/td&#62;&#60;/tr&#62;&#60;/tbody&#62;&#60;/table&#62;&#60;/div&#62;&#60;ul&#62;
&#60;li&#62;&#60;strong&#62;Last non-direct&#60;/strong&#62; credits the &#60;strong&#62;newsletter&#60;/strong&#62;. Visit 3 was direct, so the model skips it.&#60;/li&#62;
&#60;li&#62;&#60;strong&#62;First touch&#60;/strong&#62; credits &#60;strong&#62;Google organic search&#60;/strong&#62;.&#60;/li&#62;
&#60;/ul&#62;
&#60;p&#62;Now follow the subscription. The customer renews for five more months, then asks for a refund on month 3. Under either model, every renewal inherits the first payment&#38;#39;s source:&#60;/p&#62;
&#60;div class=&#34;docs-table&#34; tabindex=&#34;0&#34; role=&#34;region&#34; aria-label=&#34;Reference table&#34;&#62;&#60;table&#62;&#60;thead&#62;&#60;tr&#62;&#60;th scope=&#34;col&#34;&#62;&#60;/th&#62;&#60;th scope=&#34;col&#34;&#62;Amount&#60;/th&#62;&#60;/tr&#62;&#60;/thead&#62;&#60;tbody&#62;&#60;tr&#62;&#60;td&#62;Six payments × $29&#60;/td&#62;&#60;td&#62;$174&#60;/td&#62;&#60;/tr&#62;&#60;tr&#62;&#60;td&#62;Refund of month 3&#60;/td&#62;&#60;td&#62;−$29&#60;/td&#62;&#60;/tr&#62;&#60;tr&#62;&#60;td&#62;Net revenue credited to the source&#60;/td&#62;&#60;td&#62;$145&#60;/td&#62;&#60;/tr&#62;&#60;/tbody&#62;&#60;/table&#62;&#60;/div&#62;&#60;p&#62;Same $145, two answers, neither wrong: the newsletter closed the sale, search found the customer.&#60;/p&#62;
&#60;p&#62;One catch: this example needs the three visits linked to one person across 15 days. That takes a stored identifier, such as a first-party cookie. Without one, only visit 3 is linked to the payment, and it would count as Direct.&#60;/p&#62;
&#60;h2 id=&#34;the-metrics-that-matter&#34; tabindex=&#34;-1&#34;&#62;The metrics that matter&#60;/h2&#62;&#60;div class=&#34;docs-table&#34; tabindex=&#34;0&#34; role=&#34;region&#34; aria-label=&#34;Reference table&#34;&#62;&#60;table&#62;&#60;thead&#62;&#60;tr&#62;&#60;th scope=&#34;col&#34;&#62;Metric&#60;/th&#62;&#60;th scope=&#34;col&#34;&#62;What it tells you&#60;/th&#62;&#60;/tr&#62;&#60;/thead&#62;&#60;tbody&#62;&#60;tr&#62;&#60;td&#62;Revenue by source, campaign and landing page&#60;/td&#62;&#60;td&#62;Where money comes from (payments minus refunds)&#60;/td&#62;&#60;/tr&#62;&#60;tr&#62;&#60;td&#62;Paying customers&#60;/td&#62;&#60;td&#62;How many distinct customers each source brought&#60;/td&#62;&#60;/tr&#62;&#60;tr&#62;&#60;td&#62;Conversion rate&#60;/td&#62;&#60;td&#62;First-time buyers ÷ unique visitors&#60;/td&#62;&#60;/tr&#62;&#60;tr&#62;&#60;td&#62;Revenue per visitor (RPV)&#60;/td&#62;&#60;td&#62;Revenue ÷ unique visitors, for the same period and segment&#60;/td&#62;&#60;/tr&#62;&#60;tr&#62;&#60;td&#62;LTV by first source&#60;/td&#62;&#60;td&#62;All revenue so far from customers first won through that source&#60;/td&#62;&#60;/tr&#62;&#60;tr&#62;&#60;td&#62;Unattributed&#60;/td&#62;&#60;td&#62;The share of revenue you couldn&#38;#39;t link to a visit&#60;/td&#62;&#60;/tr&#62;&#60;/tbody&#62;&#60;/table&#62;&#60;/div&#62;&#60;p&#62;Revenue per visitor is the fairest way to compare sources of different sizes.&#60;/p&#62;
&#60;h2 id=&#34;three-ways-to-set-it-up&#34; tabindex=&#34;-1&#34;&#62;Three ways to set it up&#60;/h2&#62;&#60;h3 id=&#34;diy-utms-into-stripe-metadata&#34; tabindex=&#34;-1&#34;&#62;DIY: UTMs into Stripe metadata&#60;/h3&#62;&#60;p&#62;The cheapest route. Read UTM values in the browser when checkout starts, send them to your server, and add them to the Checkout Session&#38;#39;s &#60;code&#62;metadata&#60;/code&#62;. For subscriptions, add them to the subscription&#38;#39;s metadata too, so renewal invoices carry them. Then export payments and group by source in a spreadsheet or SQL.&#60;/p&#62;
&#60;p&#62;Stripe Payment Links also accept &#60;code&#62;utm_source&#60;/code&#62;, &#60;code&#62;utm_medium&#60;/code&#62;, &#60;code&#62;utm_campaign&#60;/code&#62;, &#60;code&#62;utm_content&#60;/code&#62; and &#60;code&#62;utm_term&#60;/code&#62; in the link URL and pass them to your redirect URL (&#60;a href=&#34;https://docs.stripe.com/payment-links/url-parameters&#34;&#62;Stripe docs&#60;/a&#62;, accessed 22 Oct 2026). Stripe warns never to put sensitive information such as card or bank details in metadata (&#60;a href=&#34;https://docs.stripe.com/metadata&#34;&#62;Stripe docs&#60;/a&#62;, accessed 22 Oct 2026).&#60;/p&#62;
&#60;p&#62;What DIY doesn&#38;#39;t give you: multiple visits, models, refunds netted against the right source, or an unattributed line. You build those yourself.&#60;/p&#62;
&#60;h3 id=&#34;ga4-stripe&#34; tabindex=&#34;-1&#34;&#62;GA4 + Stripe&#60;/h3&#62;&#60;p&#62;Google Analytics 4 can record ecommerce purchase events (&#60;a href=&#34;https://support.google.com/analytics/answer/9267735&#34;&#62;Google Analytics help: recommended events&#60;/a&#62;, accessed 22 Oct 2026). To use it for SaaS revenue, you send purchase events with amounts, usually from your server after Stripe confirms payment, and handle renewals and refunds yourself. It works, but it&#38;#39;s a real project for a small team. As the same Hacker News post puts it, &#38;quot;wiring together GA, BigQuery, and Stripe is way too much for a small team&#38;quot; (&#60;a href=&#34;https://news.ycombinator.com/item?id=44756020&#34;&#62;HN&#60;/a&#62;).&#60;/p&#62;
&#60;h3 id=&#34;a-revenue-attribution-analytics-tool&#34; tabindex=&#34;-1&#34;&#62;A revenue-attribution analytics tool&#60;/h3&#62;&#60;p&#62;These tools sync payments from your provider and do the matching for you. When comparing them, check:&#60;/p&#62;
&#60;ul&#62;
&#60;li&#62;&#60;strong&#62;Payment-provider sync&#60;/strong&#62; for the provider you use, not just an events API.&#60;/li&#62;
&#60;li&#62;&#60;strong&#62;Renewals and refunds:&#60;/strong&#62; do renewals keep their source? Are refunds subtracted?&#60;/li&#62;
&#60;li&#62;&#60;strong&#62;Unattributed handling:&#60;/strong&#62; are unmatched payments shown, or quietly assigned?&#60;/li&#62;
&#60;li&#62;&#60;strong&#62;Model choice:&#60;/strong&#62; can you compare at least two models? Is the lookback window a setting?&#60;/li&#62;
&#60;li&#62;&#60;strong&#62;Privacy default:&#60;/strong&#62; cookieless or cookie-based by default, and what each mode can link.&#60;/li&#62;
&#60;li&#62;&#60;strong&#62;What the price is based on:&#60;/strong&#62; sites, team members or event volume.&#60;/li&#62;
&#60;/ul&#62;
&#60;h3 id=&#34;how-traffic-cx-does-it&#34; tabindex=&#34;-1&#34;&#62;How traffic.cx does it&#60;/h3&#62;&#60;p&#62;traffic.cx is one tool built for this. You connect &#60;a href=&#34;/integrations/stripe&#34;&#62;Stripe&#60;/a&#62;, &#60;a href=&#34;/integrations/lemon-squeezy&#34;&#62;Lemon Squeezy&#60;/a&#62;, &#60;a href=&#34;/integrations/polar&#34;&#62;Polar&#60;/a&#62; or &#60;a href=&#34;/integrations/dodo&#34;&#62;Dodo Payments&#60;/a&#62;, or send payments through the &#60;a href=&#34;/docs/payments-api&#34;&#62;Payments API&#60;/a&#62;. Your checkout passes a pageview ID in its metadata.&#60;/p&#62;
&#60;p&#62;It offers two models, last non-direct (default) and first touch, with a toggle. The lookback window is 90 days by default and can be set from 7 to 365 days. In the default cookieless mode, a payment links only to the visit where checkout started; a longer lookback needs cookie mode (same browser only). Renewals and repeat customers inherit the attribution of the customer&#38;#39;s first payment. Refunds are subtracted on the day they happen and credited to the original payment. Payments it can&#38;#39;t match stay in totals as &#38;quot;Unattributed&#38;quot; (&#60;a href=&#34;/docs/revenue&#34;&#62;how it works&#60;/a&#62;).&#60;/p&#62;
&#60;p&#62;Plans start at $5 a month for 5,000 events, as of 22 October 2026, with unlimited sites and team members on every paid plan (&#60;a href=&#34;/pricing&#34;&#62;pricing&#60;/a&#62;). For side-by-side comparisons, see traffic.cx against &#60;a href=&#34;/compare/plausible-alternative&#34;&#62;Plausible Analytics&#60;/a&#62; and &#60;a href=&#34;/compare/datafast-alternative&#34;&#62;DataFast&#60;/a&#62;.&#60;/p&#62;
&#60;blockquote&#62;
&#60;p&#62;&#60;strong&#62;See which traffic pays.&#60;/strong&#62; Start a 7-day trial, no card needed (up to 10,000 events). Connect Stripe, Lemon Squeezy, Polar or Dodo from Settings → Revenue. &#60;a href=&#34;https://app.traffic.cx/signup&#34;&#62;Start your trial&#60;/a&#62;&#60;/p&#62;
&#60;/blockquote&#62;
&#60;h2 id=&#34;what-to-trust-and-what-not-to&#34; tabindex=&#34;-1&#34;&#62;What to trust, and what not to&#60;/h2&#62;&#60;p&#62;Attribution describes the recorded journey; it doesn&#38;#39;t prove a campaign caused a purchase.&#60;/p&#62;
&#60;h3 id=&#34;unattributed-is-not-a-failure&#34; tabindex=&#34;-1&#34;&#62;Unattributed is not a failure&#60;/h3&#62;&#60;p&#62;An unattributed payment is real revenue with no visit you can prove. Showing it keeps your total equal to what your provider received. Common causes, in order:&#60;/p&#62;
&#60;ol&#62;
&#60;li&#62;No identifier reached the payment. Check the payment&#38;#39;s metadata in your provider&#38;#39;s dashboard.&#60;/li&#62;
&#60;li&#62;The visit wasn&#38;#39;t recorded (ad blocker, missing tracker on that page).&#60;/li&#62;
&#60;li&#62;The identifier came from a different visit, such as a thank-you page on another device.&#60;/li&#62;
&#60;li&#62;The buyer came back on a later day or another device with no stored identifier.&#60;/li&#62;
&#60;li&#62;The visit fell outside the lookback window.&#60;/li&#62;
&#60;/ol&#62;
&#60;h3 id=&#34;direct-vs-unattributed&#34; tabindex=&#34;-1&#34;&#62;Direct vs Unattributed&#60;/h3&#62;&#60;p&#62;They&#38;#39;re different. &#60;strong&#62;Direct&#60;/strong&#62; means a visit was matched, and it had no source to credit: a typed URL or bookmark. &#60;strong&#62;Unattributed&#60;/strong&#62; means no visit was matched at all. A high Unattributed share usually means a broken handoff into checkout.&#60;/p&#62;
&#60;h3 id=&#34;cookieless-vs-cookie-mode-the-cross-day-tradeoff&#34; tabindex=&#34;-1&#34;&#62;Cookieless vs cookie mode: the cross-day tradeoff&#60;/h3&#62;&#60;p&#62;Cookieless analytics avoids storing an identifier in the visitor&#38;#39;s browser. The tradeoff: it can link a payment to the visit where checkout started, but not to a visit on an earlier day. traffic.cx&#38;#39;s default cookieless mode rotates visitor identity daily, so it doesn&#38;#39;t build a journey across days (&#60;a href=&#34;/docs/revenue&#34;&#62;docs&#60;/a&#62;). Other vendors describe the same tradeoff for their cookieless scripts (&#60;a href=&#34;https://datafa.st/docs/gdpr-cookieless-tracking&#34;&#62;DataFast docs&#60;/a&#62;, accessed 22 Oct 2026).&#60;/p&#62;
&#60;p&#62;A cookie mode links visits across days on the same browser, so a long lookback window can do its job. Nothing links a different device. In the worked example above, cookieless mode would credit Direct, and cookie mode would credit the newsletter.&#60;/p&#62;
&#60;h3 id=&#34;privacy-and-consent&#34; tabindex=&#34;-1&#34;&#62;Privacy and consent&#60;/h3&#62;&#60;p&#62;Linking payments to visits goes further than counting pageviews. Whether you need consent depends on your setup, the mode you use and where your visitors are. This isn&#38;#39;t legal advice; check with your adviser before switching on cookie-based tracking. For what traffic.cx collects in each mode, see its &#60;a href=&#34;/privacy&#34;&#62;privacy notice&#60;/a&#62;.&#60;/p&#62;
&#60;h2 id=&#34;a-30-minute-setup-checklist&#34; tabindex=&#34;-1&#34;&#62;A 30-minute setup checklist&#60;/h2&#62;&#60;ol&#62;
&#60;li&#62;Install your analytics script on every page, including pricing and checkout (&#60;a href=&#34;/docs/getting-started&#34;&#62;getting started&#60;/a&#62;).&#60;/li&#62;
&#60;li&#62;Verify that a test visit shows up with the right source.&#60;/li&#62;
&#60;li&#62;Agree on UTM naming: lowercase, underscores, one shared list.&#60;/li&#62;
&#60;li&#62;Connect your payment provider (or plan your webhook handler for DIY).&#60;/li&#62;
&#60;li&#62;In your checkout code, read the visit identifier when checkout starts.&#60;/li&#62;
&#60;li&#62;Add it to the checkout&#38;#39;s metadata, and to the subscription&#38;#39;s metadata for subscriptions.&#60;/li&#62;
&#60;li&#62;Open a tagged link, such as &#60;code&#62;?utm_source=setup-check&#38;amp;utm_medium=email&#38;amp;utm_campaign=test&#60;/code&#62;.&#60;/li&#62;
&#60;li&#62;Complete a test payment in your provider&#38;#39;s test mode.&#60;/li&#62;
&#60;li&#62;Confirm the payment appears once, with the expected source and campaign.&#60;/li&#62;
&#60;li&#62;Test a refund and check that revenue drops on the refund date.&#60;/li&#62;
&#60;li&#62;Pick a default model and lookback window, and write them down.&#60;/li&#62;
&#60;li&#62;Check the unattributed share weekly for the first month.&#60;/li&#62;
&#60;/ol&#62;
&#60;h2 id=&#34;faq&#34; tabindex=&#34;-1&#34;&#62;FAQ&#60;/h2&#62;&#60;h3 id=&#34;what-is-revenue-attribution-2&#34; tabindex=&#34;-1&#34;&#62;What is revenue attribution?&#60;/h3&#62;&#60;p&#62;Crediting each payment to the source, campaign or page that brought the customer. It lets you compare channels by revenue rather than visits.&#60;/p&#62;
&#60;h3 id=&#34;what-is-a-revenue-attribution-model&#34; tabindex=&#34;-1&#34;&#62;What is a revenue attribution model?&#60;/h3&#62;&#60;p&#62;The rule that decides which visit gets credit when a customer visited more than once, such as last non-direct or first touch.&#60;/p&#62;
&#60;h3 id=&#34;first-touch-or-last-touch-which-should-a-small-saas-use&#34; tabindex=&#34;-1&#34;&#62;First touch or last touch: which should a small SaaS use?&#60;/h3&#62;&#60;p&#62;Start with last non-direct to see what closes sales, then check first touch to see what finds customers. Compare both before moving budget.&#60;/p&#62;
&#60;h3 id=&#34;how-do-i-know-which-marketing-channel-produces-my-paying-customers&#34; tabindex=&#34;-1&#34;&#62;How do I know which marketing channel produces my paying customers?&#60;/h3&#62;&#60;p&#62;Carry a visit identifier from your site into checkout, then match each payment back to that visit. Do it yourself with UTMs in Stripe metadata, or use a tool that syncs your payment provider.&#60;/p&#62;
&#60;h3 id=&#34;why-do-customers-who-found-me-weeks-ago-show-up-as-direct&#34; tabindex=&#34;-1&#34;&#62;Why do customers who found me weeks ago show up as &#38;quot;direct&#38;quot;?&#60;/h3&#62;&#60;p&#62;Their last visit was typed or bookmarked. Last-touch models credit it unless they skip direct visits, and linking visits across days needs a stored identifier.&#60;/p&#62;
&#60;h3 id=&#34;doesn-t-stripe-show-where-customers-came-from&#34; tabindex=&#34;-1&#34;&#62;Doesn&#38;#39;t Stripe show where customers came from?&#60;/h3&#62;&#60;p&#62;Not by itself. Stripe records payments, not marketing sources. You pass source data into checkout metadata or use a connected analytics tool.&#60;/p&#62;
&#60;h3 id=&#34;what-should-a-revenue-attribution-report-show&#34; tabindex=&#34;-1&#34;&#62;What should a revenue attribution report show?&#60;/h3&#62;&#60;p&#62;Revenue, paying customers, conversion rate and revenue per visitor by source, campaign and landing page, plus an unattributed line.&#60;/p&#62;
&#60;h3 id=&#34;what-is-revenue-per-visitor&#34; tabindex=&#34;-1&#34;&#62;What is revenue per visitor?&#60;/h3&#62;&#60;p&#62;Revenue divided by unique visitors, for the same period and segment.&#60;/p&#62;
&#60;h3 id=&#34;should-renewals-be-credited-to-the-original-source&#34; tabindex=&#34;-1&#34;&#62;Should renewals be credited to the original source?&#60;/h3&#62;&#60;p&#62;For subscription businesses, usually yes. The renewal was earned by whatever acquired the customer.&#60;/p&#62;
&#60;h3 id=&#34;is-how-did-you-hear-about-us-enough&#34; tabindex=&#34;-1&#34;&#62;Is &#38;quot;how did you hear about us?&#38;quot; enough?&#60;/h3&#62;&#60;p&#62;It&#38;#39;s a useful cross-check, but answers are incomplete and fuzzy. Use it alongside tracked attribution.&#60;/p&#62;
&#60;h3 id=&#34;do-i-need-consent-for-revenue-attribution&#34; tabindex=&#34;-1&#34;&#62;Do I need consent for revenue attribution?&#60;/h3&#62;&#60;p&#62;It depends on your setup and where your visitors are. Linking payments to visits is more than counting pageviews, so check with your adviser.&#60;/p&#62;
&#60;h2 id=&#34;see-revenue-by-source-on-your-own-site&#34; tabindex=&#34;-1&#34;&#62;See revenue by source on your own site&#60;/h2&#62;&#60;p&#62;Start a 7-day trial, no card needed, with up to 10,000 events.&#60;/p&#62;
&#60;p&#62;&#60;a href=&#34;https://app.traffic.cx/signup&#34;&#62;Start your trial&#60;/a&#62; · &#60;a href=&#34;https://demo.traffic.cx&#34;&#62;See the live demo&#60;/a&#62; · &#60;a href=&#34;/features/revenue-attribution&#34;&#62;How revenue attribution works&#60;/a&#62; · &#60;a href=&#34;/blog/utm-revenue-attribution&#34;&#62;Track a UTM campaign through to revenue&#60;/a&#62;&#60;/p&#62;
</content>
  </entry>
  <entry>
    <id>https://traffic.cx/blog/utm-revenue-attribution</id>
    <title>Track a UTM Campaign Through to Revenue</title>
    <link rel="alternate" type="text/html" href="https://traffic.cx/blog/utm-revenue-attribution"/>
    <published>2026-10-15T00:00:00.000Z</published>
    <updated>2026-10-15T00:00:00.000Z</updated>
    <author><name>Karthick</name></author>
    <category term="utm" label="UTM"/>
    <category term="revenue-attribution" label="Revenue attribution"/>
    <category term="campaigns" label="Campaigns"/>
    <summary>A tested walkthrough: tag a campaign link, carry the visit into checkout, see which campaign earned the payment, and fix revenue that shows as Unattributed.</summary>
    <content type="html">&#60;p&#62;Campaign tags tell you which link brought a visitor. Revenue attribution tells you which of those visitors paid. This guide connects the two with one tagged link, one visit, one checkout and one payment, then shows the report and what to check when a payment arrives without its campaign.&#60;/p&#62;
&#60;p&#62;We ran every step below on a traffic.cx test site on 15 October 2026, with the real tracker in a browser and a payment sent through the Payments API. The amounts are test payments, not customer results.&#60;/p&#62;
&#60;h2 id=&#34;what-you-need&#34; tabindex=&#34;-1&#34;&#62;What you need&#60;/h2&#62;&#60;ul&#62;
&#60;li&#62;The traffic.cx tracker on your site. See &#60;a href=&#34;/docs/getting-started&#34;&#62;install and verify your first visit&#60;/a&#62;.&#60;/li&#62;
&#60;li&#62;A way to send payments: a connected provider (&#60;a href=&#34;/integrations/stripe&#34;&#62;Stripe&#60;/a&#62;, &#60;a href=&#34;/integrations/dodo&#34;&#62;Dodo Payments&#60;/a&#62;, &#60;a href=&#34;/integrations/lemon-squeezy&#34;&#62;Lemon Squeezy&#60;/a&#62; or &#60;a href=&#34;/integrations/polar&#34;&#62;Polar&#60;/a&#62;) or the &#60;a href=&#34;/docs/payments-api&#34;&#62;Payments API&#60;/a&#62;.&#60;/li&#62;
&#60;li&#62;A campaign link you control, such as a newsletter, a social post or an ad.&#60;/li&#62;
&#60;/ul&#62;
&#60;h2 id=&#34;1-tag-the-link&#34; class=&#34;step-heading&#34; tabindex=&#34;-1&#34;&#62;&#60;span class=&#34;sr-only&#34;&#62;1. &#60;/span&#62;Tag the link&#60;/h2&#62;&#60;p&#62;Add three tags to the link you share:&#60;/p&#62;
&#60;div class=&#34;code-example&#34;&#62;&#60;div class=&#34;code-head&#34;&#62;&#60;p class=&#34;code-language&#34;&#62;text&#60;/p&#62;&#60;/div&#62;&#60;pre tabindex=&#34;0&#34; aria-label=&#34;text example&#34;&#62;&#60;code&#62;https://example.com/pricing?utm_source=newsletter&#38;amp;utm_medium=email&#38;amp;utm_campaign=october_newsletter&#60;/code&#62;&#60;/pre&#62;&#60;/div&#62;&#60;ul&#62;
&#60;li&#62;&#60;code&#62;utm_source&#60;/code&#62; names where the link was placed: &#60;code&#62;newsletter&#60;/code&#62;, &#60;code&#62;x&#60;/code&#62;, &#60;code&#62;producthunt&#60;/code&#62;. traffic.cx uses it as the visit&#38;#39;s source, ahead of the referrer.&#60;/li&#62;
&#60;li&#62;&#60;code&#62;utm_medium&#60;/code&#62; names the kind of traffic. It decides the channel: &#60;code&#62;email&#60;/code&#62; groups the visit under Email, and mediums such as &#60;code&#62;cpc&#60;/code&#62;, &#60;code&#62;ppc&#60;/code&#62; or &#60;code&#62;paid_social&#60;/code&#62; group it under a paid channel.&#60;/li&#62;
&#60;li&#62;&#60;code&#62;utm_campaign&#60;/code&#62; names the campaign. This is the row you will look for in the revenue report.&#60;/li&#62;
&#60;/ul&#62;
&#60;p&#62;&#60;code&#62;utm_content&#60;/code&#62; and &#60;code&#62;utm_term&#60;/code&#62; are optional and are recorded too, for telling apart two links in the same campaign.&#60;/p&#62;
&#60;p&#62;Tag values are stored as you write them, so &#60;code&#62;Newsletter&#60;/code&#62; and &#60;code&#62;newsletter&#60;/code&#62; become two campaigns. Pick lowercase names with underscores and keep them in one place. Never put an email address, name or customer ID in a tag: campaign links get shared, logged and forwarded.&#60;/p&#62;
&#60;h2 id=&#34;2-check-that-the-visit-arrived&#34; class=&#34;step-heading&#34; tabindex=&#34;-1&#34;&#62;&#60;span class=&#34;sr-only&#34;&#62;2. &#60;/span&#62;Check that the visit arrived&#60;/h2&#62;&#60;p&#62;Open the link in a normal browser window, then open &#60;strong&#62;Overview&#60;/strong&#62; in traffic.cx for today. The sources panel lists the visit&#38;#39;s source, and its campaign tab lists &#60;code&#62;october_newsletter&#60;/code&#62;. The tags belong to the visit&#38;#39;s first page, so the visit should show:&#60;/p&#62;
&#60;div class=&#34;docs-table&#34; tabindex=&#34;0&#34; role=&#34;region&#34; aria-label=&#34;Reference table&#34;&#62;&#60;table&#62;&#60;thead&#62;&#60;tr&#62;&#60;th scope=&#34;col&#34;&#62;Field&#60;/th&#62;&#60;th scope=&#34;col&#34;&#62;In our test&#60;/th&#62;&#60;/tr&#62;&#60;/thead&#62;&#60;tbody&#62;&#60;tr&#62;&#60;td&#62;Source&#60;/td&#62;&#60;td&#62;newsletter&#60;/td&#62;&#60;/tr&#62;&#60;tr&#62;&#60;td&#62;Channel&#60;/td&#62;&#60;td&#62;Email&#60;/td&#62;&#60;/tr&#62;&#60;tr&#62;&#60;td&#62;Campaign&#60;/td&#62;&#60;td&#62;october_newsletter&#60;/td&#62;&#60;/tr&#62;&#60;tr&#62;&#60;td&#62;Landing page&#60;/td&#62;&#60;td&#62;/pricing&#60;/td&#62;&#60;/tr&#62;&#60;/tbody&#62;&#60;/table&#62;&#60;/div&#62;&#60;p&#62;If the visit is missing, check that the tracker loads on that page and that no ad blocker or excluded path is stopping it. The &#60;a href=&#34;/docs/getting-started&#34;&#62;getting started checks&#60;/a&#62; cover this.&#60;/p&#62;
&#60;h2 id=&#34;3-carry-the-visit-into-checkout&#34; class=&#34;step-heading&#34; tabindex=&#34;-1&#34;&#62;&#60;span class=&#34;sr-only&#34;&#62;3. &#60;/span&#62;Carry the visit into checkout&#60;/h2&#62;&#60;p&#62;A payment provider doesn&#38;#39;t know which visit started the checkout. Give it the visit&#38;#39;s pageview ID when the visitor starts checkout, not later on a thank-you page:&#60;/p&#62;
&#60;div class=&#34;code-example&#34;&#62;&#60;div class=&#34;code-head&#34;&#62;&#60;p class=&#34;code-language&#34;&#62;js&#60;/p&#62;&#60;/div&#62;&#60;pre tabindex=&#34;0&#34; aria-label=&#34;js example&#34;&#62;&#60;code&#62;const tcx = {
  tcx_pvid: window.trafficcx?.pageviewId?.() ?? &#39;&#39;,
  tcx_vid: window.trafficcx?.visitorId?.() ?? &#39;&#39;, // cookie mode only
};
// Send tcx to your server with the checkout request.&#60;/code&#62;&#60;/pre&#62;&#60;/div&#62;&#60;p&#62;Your server puts these values in the provider&#38;#39;s checkout metadata, or saves them with the order to send through the Payments API later. Each &#60;a href=&#34;/docs/revenue#pass-identifiers-to-checkout&#34;&#62;provider guide&#60;/a&#62; shows where they go.&#60;/p&#62;
&#60;p&#62;In the default cookieless mode, the pageview ID links a purchase made during the same visit. If people often leave and come back days later to buy, cookie mode&#38;#39;s visitor ID also links their earlier visits. See &#60;a href=&#34;/docs/revenue#cookieless-mode-versus-cookie-mode&#34;&#62;cookieless mode versus cookie mode&#60;/a&#62;.&#60;/p&#62;
&#60;h2 id=&#34;4-record-the-payment&#34; class=&#34;step-heading&#34; tabindex=&#34;-1&#34;&#62;&#60;span class=&#34;sr-only&#34;&#62;4. &#60;/span&#62;Record the payment&#60;/h2&#62;&#60;p&#62;With a connected provider, the payment arrives on its own. With the Payments API, your server sends it once the payment has succeeded:&#60;/p&#62;
&#60;div class=&#34;code-example&#34;&#62;&#60;div class=&#34;code-head&#34;&#62;&#60;p class=&#34;code-language&#34;&#62;bash&#60;/p&#62;&#60;/div&#62;&#60;pre tabindex=&#34;0&#34; aria-label=&#34;bash example&#34;&#62;&#60;code&#62;curl -X POST https://api.traffic.cx/v1/payments \
  -H &#38;quot;Authorization: Bearer YOUR_API_KEY&#38;quot; \
  -H &#38;quot;Content-Type: application/json&#38;quot; \
  -d &#39;{
    &#38;quot;site&#38;quot;: &#38;quot;tcx_yoursite&#38;quot;,
    &#38;quot;transaction_id&#38;quot;: &#38;quot;order_1001&#38;quot;,
    &#38;quot;amount&#38;quot;: 49,
    &#38;quot;currency&#38;quot;: &#38;quot;USD&#38;quot;,
    &#38;quot;pageview_id&#38;quot;: &#38;quot;THE_SAVED_TCX_PVID&#38;quot;
  }&#39;&#60;/code&#62;&#60;/pre&#62;&#60;/div&#62;&#60;p&#62;In our test, the answer confirmed the link straight away:&#60;/p&#62;
&#60;div class=&#34;code-example&#34;&#62;&#60;div class=&#34;code-head&#34;&#62;&#60;p class=&#34;code-language&#34;&#62;json&#60;/p&#62;&#60;/div&#62;&#60;pre tabindex=&#34;0&#34; aria-label=&#34;json example&#34;&#62;&#60;code&#62;{
  &#38;quot;ok&#38;quot;: true,
  &#38;quot;transaction_id&#38;quot;: &#38;quot;guide_order_…_1&#38;quot;,
  &#38;quot;attributed&#38;quot;: true,
  &#38;quot;amount_reporting&#38;quot;: &#38;quot;49.0000&#38;quot;,
  &#38;quot;currency_reporting&#38;quot;: &#38;quot;USD&#38;quot;,
  &#38;quot;channel&#38;quot;: &#38;quot;Email&#38;quot;,
  &#38;quot;source&#38;quot;: &#38;quot;newsletter&#38;quot;
}&#60;/code&#62;&#60;/pre&#62;&#60;/div&#62;&#60;p&#62;To see what a broken handoff looks like, we also sent a $29 payment without a pageview ID. It was recorded with &#60;code&#62;&#38;quot;attributed&#38;quot;: false&#60;/code&#62;.&#60;/p&#62;
&#60;h2 id=&#34;5-read-the-report&#34; class=&#34;step-heading&#34; tabindex=&#34;-1&#34;&#62;&#60;span class=&#34;sr-only&#34;&#62;5. &#60;/span&#62;Read the report&#60;/h2&#62;&#60;p&#62;Open &#60;strong&#62;Revenue&#60;/strong&#62; and choose &#60;strong&#62;Campaigns&#60;/strong&#62; in the attribution table. Each campaign shows its revenue, paying customers, visitors, revenue per visitor (RPV), conversion rate (CR) and lifetime value (LTV). Recent payments below list each payment with its source and landing page.&#60;/p&#62;
&#60;figure class=&#34;screenshot&#34;&#62;&#60;img src=&#34;/images/guides/utm-revenue-light.png&#34; alt=&#34;The traffic.cx Revenue page from our test: october_newsletter earned $49 from one visitor, and a $29 payment without a pageview ID shows as Unattributed.&#34; width=&#34;2056&#34; height=&#34;816&#34; loading=&#34;lazy&#34; decoding=&#34;async&#34;&#62;&#60;/figure&#62;
&#60;p&#62;The $49 payment is credited to &#60;code&#62;october_newsletter&#60;/code&#62;, with newsletter and Email as its source and channel. The $29 payment stays in the total as Unattributed instead of being given a source we can&#38;#39;t prove.&#60;/p&#62;
&#60;p&#62;The table uses &#60;strong&#62;last non-direct&#60;/strong&#62; attribution by default: the most recent visit before the payment that wasn&#38;#39;t direct gets the credit, so a visitor who comes back by typing your address doesn&#38;#39;t erase the newsletter. Switch to &#60;strong&#62;First touch&#60;/strong&#62; to credit the earliest visit instead. &#60;a href=&#34;/docs/revenue#attribution-models&#34;&#62;Attribution models&#60;/a&#62; explains both.&#60;/p&#62;
&#60;h2 id=&#34;what-we-expected-and-what-we-saw&#34; tabindex=&#34;-1&#34;&#62;What we expected and what we saw&#60;/h2&#62;&#60;div class=&#34;docs-table&#34; tabindex=&#34;0&#34; role=&#34;region&#34; aria-label=&#34;Reference table&#34;&#62;&#60;table&#62;&#60;thead&#62;&#60;tr&#62;&#60;th scope=&#34;col&#34;&#62;Step&#60;/th&#62;&#60;th scope=&#34;col&#34;&#62;Expected&#60;/th&#62;&#60;th scope=&#34;col&#34;&#62;Observed on 15 October 2026&#60;/th&#62;&#60;/tr&#62;&#60;/thead&#62;&#60;tbody&#62;&#60;tr&#62;&#60;td&#62;Visit from the tagged link&#60;/td&#62;&#60;td&#62;Source newsletter, channel Email, campaign october_newsletter&#60;/td&#62;&#60;td&#62;All three recorded, landing page /pricing&#60;/td&#62;&#60;/tr&#62;&#60;tr&#62;&#60;td&#62;$49 payment with the pageview ID&#60;/td&#62;&#60;td&#62;Credited to october_newsletter&#60;/td&#62;&#60;td&#62;&#60;code&#62;attributed: true&#60;/code&#62;, source newsletter, channel Email&#60;/td&#62;&#60;/tr&#62;&#60;tr&#62;&#60;td&#62;$29 payment without an ID&#60;/td&#62;&#60;td&#62;Kept in revenue as Unattributed&#60;/td&#62;&#60;td&#62;&#60;code&#62;attributed: false&#60;/code&#62;, listed as Unattributed&#60;/td&#62;&#60;/tr&#62;&#60;tr&#62;&#60;td&#62;Revenue page, Campaigns&#60;/td&#62;&#60;td&#62;october_newsletter $49, Unattributed $29&#60;/td&#62;&#60;td&#62;As expected; total $78&#60;/td&#62;&#60;/tr&#62;&#60;/tbody&#62;&#60;/table&#62;&#60;/div&#62;&#60;h2 id=&#34;when-revenue-shows-as-unattributed&#34; tabindex=&#34;-1&#34;&#62;When revenue shows as Unattributed&#60;/h2&#62;&#60;p&#62;Work through these in order. The first one is the most common.&#60;/p&#62;
&#60;ol&#62;
&#60;li&#62;&#60;strong&#62;No ID reached the payment.&#60;/strong&#62; Open the payment in your provider&#38;#39;s dashboard and look for &#60;code&#62;tcx_pvid&#60;/code&#62; in its metadata. For the Payments API, log the body you send. An empty value usually means the checkout code ran before the tracker loaded, or didn&#38;#39;t run at all.&#60;/li&#62;
&#60;li&#62;&#60;strong&#62;The visit wasn&#38;#39;t recorded.&#60;/strong&#62; An ad blocker, an excluded path or a page without the tracker means there&#38;#39;s no visit for the ID to point to. Check that the visit appears in Overview while you test.&#60;/li&#62;
&#60;li&#62;&#60;strong&#62;The ID came from a different visit.&#60;/strong&#62; An ID read on a thank-you page can belong to a later visit than the one that started checkout, for example when the buyer finishes paying on another device. Save the ID when checkout starts and send that one.&#60;/li&#62;
&#60;li&#62;&#60;strong&#62;The buyer came back later.&#60;/strong&#62; In cookieless mode, a purchase on a later day or another device has no link to the campaign visit. Cookie mode helps with later days on the same browser; nothing links a different device.&#60;/li&#62;
&#60;li&#62;&#60;strong&#62;The visit is outside the lookback window.&#60;/strong&#62; The default is 90 days. You can set 7 to 365 days in &#60;strong&#62;Settings → Revenue&#60;/strong&#62;.&#60;/li&#62;
&#60;/ol&#62;
&#60;p&#62;&#60;a href=&#34;/docs/revenue#verify-and-diagnose-attribution&#34;&#62;Verify and diagnose attribution&#60;/a&#62; covers provider-specific checks.&#60;/p&#62;
&#60;h2 id=&#34;when-the-campaign-is-missing-or-wrong&#34; tabindex=&#34;-1&#34;&#62;When the campaign is missing or wrong&#60;/h2&#62;&#60;ul&#62;
&#60;li&#62;&#60;strong&#62;The tags were stripped.&#60;/strong&#62; Link shorteners, redirects and some email tools can drop the query string. Open the link as a reader would and check the address bar on the page that loads.&#60;/li&#62;
&#60;li&#62;&#60;strong&#62;The values don&#38;#39;t match.&#60;/strong&#62; &#60;code&#62;October_Newsletter&#60;/code&#62; and &#60;code&#62;october_newsletter&#60;/code&#62; are separate rows. Fix the link and use one spelling from then on.&#60;/li&#62;
&#60;li&#62;&#60;strong&#62;The visit was credited to something else.&#60;/strong&#62; Under last non-direct, a later visit from another campaign or search takes the credit. Switch to First touch to see whether your campaign started the journey.&#60;/li&#62;
&#60;li&#62;&#60;strong&#62;The medium put it in a different channel.&#60;/strong&#62; A medium such as &#60;code&#62;newsletter&#60;/code&#62; instead of &#60;code&#62;email&#60;/code&#62; won&#38;#39;t group under Email. Use the standard medium names for your channel reports.&#60;/li&#62;
&#60;/ul&#62;
&#60;h2 id=&#34;next-steps&#34; tabindex=&#34;-1&#34;&#62;Next steps&#60;/h2&#62;&#60;ul&#62;
&#60;li&#62;Set up your provider: &#60;a href=&#34;/integrations/stripe&#34;&#62;Stripe&#60;/a&#62;, &#60;a href=&#34;/integrations/dodo&#34;&#62;Dodo Payments&#60;/a&#62;, &#60;a href=&#34;/integrations/lemon-squeezy&#34;&#62;Lemon Squeezy&#60;/a&#62;, &#60;a href=&#34;/integrations/polar&#34;&#62;Polar&#60;/a&#62; or the &#60;a href=&#34;/docs/payments-api&#34;&#62;Payments API&#60;/a&#62;.&#60;/li&#62;
&#60;li&#62;Read &#60;a href=&#34;/docs/revenue&#34;&#62;how revenue attribution works&#60;/a&#62; for refunds, renewals and repeat customers.&#60;/li&#62;
&#60;li&#62;See &#60;a href=&#34;/features/revenue-attribution&#34;&#62;what revenue attribution shows&#60;/a&#62;, or compare &#60;a href=&#34;/pricing&#34;&#62;plans and the free trial&#60;/a&#62;.&#60;/li&#62;
&#60;/ul&#62;
</content>
  </entry>
</feed>
