How to Track Meta and Google Ads ROAS Through to Stripe Subscriptions

A step-by-step setup for SaaS teams: name campaigns so they survive the trip, link each Stripe payment to the visit that caused it, and read platform ROAS next to Stripe-verified ROAS without mixing the two.

How to Track Meta and Google Ads ROAS Through to Stripe Subscriptions

The short answer: As of October 8, 2026, tracking ad ROAS through to Stripe subscriptions takes three links: put the campaign name in utm_campaign on every ad, connect each Stripe payment to the site visit that caused it, and divide matched Stripe revenue by spend for the same campaign and dates. Meta can fill utm_campaign for you with {{campaign.name}}. Google Ads cannot insert campaign names, so you set it by hand per campaign. Attach the visit to the Stripe Subscription or Customer, not only the first payment, and renewals stay tied to the campaign that won them.

This guide is for SaaS and subscription teams that run paid traffic from Meta or Google Ads to their own site and bill through Stripe. Ecommerce attribution guides assume one order equals one sale. A subscription is different: the click becomes a trial, the trial maybe becomes a first invoice, and the first invoice becomes months of renewals. Each step can break the chain back to the ad.

TL;DR

  • Two ROAS numbers exist: the one the ad platform reports and the one your Stripe account can verify. Read them side by side. Never add them together or swap one for the other.
  • Meta: add utm_campaign={{campaign.name}} in URL parameters. The value freezes at first publish, so renaming a campaign later does not rename its traffic.
  • Google Ads: there is no campaign-name ValueTrack parameter. Put utm_campaign=<exact campaign name> in each campaign's final URL suffix.
  • Stripe: store the visitor's session ID on the Subscription or Customer. Stripe copies subscription metadata onto every invoice it creates.
  • Expect a lag. A campaign that starts many trials this month shows little Stripe revenue until those trials convert.

Platform ROAS and Stripe ROAS are two different numbers

Platform ROAS is what Meta Ads Manager or Google Ads reports: conversions the platform credits to an ad inside its own attribution window. On Meta that window can include view-through, people who saw the ad and converted later without clicking. Stripe ROAS is money your Stripe account actually collected from visitors who arrived from that campaign, divided by that campaign's spend.

Neither number is "true". They answer different questions. The platform number is what the delivery algorithm optimizes against, so you still need it to be set up well. The Stripe number is what your finance team will recognize. The useful signal is the gap between them, per campaign: a campaign with strong platform ROAS and weak Stripe ROAS is being credited for revenue the processor cannot see coming from it.

For subscriptions there is a third trap. If you send trial starts to Meta as the conversion event, Meta's ROAS treats every trial as value. Trials that never pay show up as conversions in the platform and as zero in Stripe.

Step 1: Name campaigns so the name survives the click

Attribution by utm_campaign only works if the value that lands on your site matches the campaign name your tools expect. The two platforms handle this differently.

Meta: use dynamic parameters, and know that names freeze

In Ads Manager, open the ad, find Tracking, and add URL parameters such as:

utm_source=facebook&utm_medium=paid&utm_campaign={{campaign.name}}&utm_content={{ad.name}}

Meta fills {{campaign.name}} and {{ad.name}} automatically. One detail matters for attribution: name-based parameters take the name used when the ad was first published. If you rename the campaign later, the traffic keeps arriving with the old name. Meta's help center says so directly and notes that changing URL parameters after publishing may send the ad set back into the learning phase (Meta, Specifications for dynamic URL parameters).

So settle campaign names before launch. If you must rename, expect two names in your reports for the same campaign.

Google Ads ValueTrack parameters include {campaignid}, the campaign ID, but no parameter for the campaign name (Google Ads Help, Set up tracking with ValueTrack parameters). If you match on names, set the name yourself in each campaign's final URL suffix:

utm_source=google&utm_medium=cpc&utm_campaign=Brand_Search_US

The final URL suffix can be set at account, campaign and ad group level (Google Ads Help, Add a final URL suffix). Set it at campaign level so each campaign carries its own name. An account-level suffix with one hardcoded name would send every campaign's traffic in as the same campaign.

Check before you spend

Click your own live ad, or use the platform's preview, and confirm the landing URL carries the utm_campaign you expect. A typo here is the most common reason a campaign shows spend and no revenue.

UTMs tell you which campaign sent a visitor. Something still has to tell you which visitor became which Stripe payment. There are three common ways to make that link, from most to least reliable.

Method How the link is made Best for Weak spot
Metadata on Stripe objects Your backend writes the visitor's session ID into metadata on the Subscription, Customer, Checkout Session or PaymentIntent Custom checkout built on the Stripe API Needs a small code change
Checkout Session ID on the return URL The Payment Link or Checkout success URL includes {CHECKOUT_SESSION_ID}, which your analytics reads on the thank-you page Stripe Payment Links, no code Breaks if the buyer pays on a different device or never reaches the thank-you page
Email match Your site identifies the visitor by email and the processor record is matched on the same email Stripe Elements and other custom flows Depends on the same email being used in both places

Why the Subscription object matters

For a subscription, put the session ID on the Subscription or the Customer, not only on the first payment. Stripe's documentation says metadata does not normally copy between objects, with listed exceptions. One of them is Subscription to Invoice: when a subscription creates an invoice, its metadata is copied onto the invoice as a one-time snapshot (Stripe Docs, Metadata). Every renewal invoice therefore carries the same marker back to the original visit.

In Humblytics, that marker is the humblytics_view_id. Read it on the page with window.Humblytics.viewId, send it to your backend with the checkout request, and add it to the metadata of the object you create:

const subscription = await stripe.subscriptions.create({
  customer: customerId,
  items: [{ price: priceId }],
  metadata: { humblytics_view_id },
});

Humblytics looks for the first humblytics_view_id across PaymentIntents, Invoices, Subscriptions, Checkout Sessions and Customers. If it is stored on a Subscription or Customer, future invoices and payments for that customer are attributed too (Humblytics Docs, Stripe API). Use a restricted Stripe key with read-only permissions when you connect it.

If you sell through Payment Links, add ?stripe_session_id={CHECKOUT_SESSION_ID} to the confirmation page URL instead. It needs no code, but it only works when the buyer finishes on the same browser that saw the ad (Humblytics Docs, Stripe Payment Links).

Step 3: Bring spend in and match it by campaign

Now you have revenue tied to campaigns. The last piece is spend for the same campaigns and dates. You can export spend from each platform and join it in a spreadsheet on utm_campaign and date. That works for a monthly check, and it is the right first step if you have never compared the numbers.

For an ongoing view, connect the ad accounts directly. In Humblytics, Meta and Google Ads connect read-only from Connectors. Spend, impressions and clicks come in per campaign, and sessions, Stripe trials and Stripe revenue are matched to them by utm_campaign. The report puts both sides of each campaign on one row:

  • Platform-reported: spend, impressions, clicks and the conversions the platform claims, inside its own attribution window.
  • Stripe-verified: sessions, trial starts, collected revenue, ROAS, cost per trial and true cost per acquisition.

Two lists in the same report do the hygiene work for you. Unmatched ad campaigns are campaigns with spend but no matching utm_campaign on the site: usually a tagging mistake from Step 1. Unmatched UTM campaigns are sessions or revenue with no ad spend behind them, usually email or organic links that reuse a UTM.

Step 4: Read subscription ROAS with the lag in mind

Subscription revenue arrives late. A useful rule for reading the numbers:

  • Trial starts are counted on the day Stripe starts the trial.
  • Revenue is counted on the day Stripe collects payment. A trial's revenue appears only once the trial converts.
  • Renewals keep adding revenue to the original campaign for as long as the subscription carries the marker.

So a campaign launched this month will look worse on Stripe ROAS than it will in sixty days. Two ways to handle that:

  1. Compare cost per trial now, ROAS later. Cost per trial is available immediately and is fair across campaigns of the same age.
  2. Compare cohorts, not calendar months. Judge a campaign on the revenue its trials produced over the same number of days since they started, so old and new campaigns are measured on equal terms.

A worked example, with hypothetical numbers: a campaign spends $4,000 in September and starts 80 trials. Meta reports 80 conversions and, valued at your plan price, a healthy ROAS. By October 8, 18 of those trials have converted to a $79 plan. Stripe-verified revenue is 18 × $79 = $1,422, a Stripe ROAS of 0.36 so far. That is not a failing campaign yet. It is a campaign whose answer is not in. Its cost per trial ($50) can already be compared with your other campaigns.

What this setup does not measure

Be precise about the limits, so nobody reads more into the report than it contains.

  • Last touch, first-party UTM. Credit goes to the campaign on the visit that led to the payment. This is not multi-touch attribution.
  • No view-through. People who saw an ad and came back by typing your URL arrive as direct traffic. That is part of the gap between platform and Stripe numbers.
  • No incrementality. A matched sale shows a campaign was on the path, not that the sale would not have happened anyway. Holdout or lift tests answer that question.
  • Cross-device journeys break the Payment Links method and weaken the others.
  • Coverage. Humblytics connects Meta and Google Ads for spend, and Stripe and Foxy for revenue. TikTok, LinkedIn and Microsoft Ads are not connected. If you need them, look at tools that cover them, such as Triple Whale, Northbeam, Polar Analytics or Rockerbox. Our comparison of Meta ads attribution tools covers the trade-offs.

How Humblytics fits

Humblytics puts the ad, the landing page, the A/B test and the Stripe payment in one place. When Stripe ROAS shows a campaign underperforming, you can open the landing page it sends traffic to, see where visitors drop off on a heatmap, and test a new version against revenue rather than clicks.

  • Pricing: Business is $79 a month, Scale is $279 a month, Enterprise is custom. See pricing.
  • Setup: connect Stripe with a restricted read-only key, connect Meta and Google Ads from Connectors, and add the script to your site.
  • AI access: an assistant such as Claude or Codex can read campaign spend next to Stripe revenue through the Humblytics MCP server and propose a test. See skills.

Read how the Stripe link works on the revenue attribution page, or start a 14-day trial and connect one ad account first.

Sources and freshness

  • Meta Business Help Center, Specifications for dynamic URL parameters in Meta Ads Manager, retrieved October 8, 2026. Supports {{campaign.name}} and {{ad.name}}, names freezing at first publish, and the learning-phase note.
  • Google Ads Help, Set up tracking with ValueTrack parameters, retrieved October 8, 2026. Supports {campaignid} as the campaign parameter and the absence of a campaign-name parameter.
  • Google Ads Help, Add a final URL suffix, retrieved October 8, 2026. Supports setting the suffix at account, campaign and ad group level.
  • Stripe Docs, Metadata, retrieved October 8, 2026. Supports metadata not copying between objects by default and the Subscription to Invoice exception.
  • Humblytics Docs, Stripe API and Stripe Payment Links, retrieved October 8, 2026. Supports humblytics_view_id, the objects checked, and the Payment Links redirect.
  • Humblytics ads attribution report definitions (Humblytics MCP get_ads_attribution), checked October 8, 2026. Supports utm_campaign matching, trial and revenue dating, and the unmatched campaign lists.

The worked example uses hypothetical numbers. Ad platform settings and interfaces change; check the linked help pages before you rely on a specific menu path.