Skip to content

Setup

Meta Ads and Stripe: see which campaigns produced Stripe payments

To tie Meta ad clicks to Stripe payments, tag your ad URLs with UTM parameters, connect Stripe with a restricted key, and make sure each checkout carries the visitor's session. Then each payment can be matched back to the campaign and click that started it.

Here's why it takes three steps. Meta sees the click. Stripe sees the payment. Nothing joins the two unless you carry something across. One r/PPC poster ran into exactly this: "I've recently discovered that I can't put my meta pixel on my Stripe checkout page." (r/PPC, November 2024)

What you need

Access to the ad in Meta Ads Manager.

A Stripe account with access to the API keys page and permission to create a restricted key (Thexly Stripe guide).

The Thexly tracking script on your site (docs).

What we checked, and how

On 16 October 2026 we read Meta's help page on URL parameters, Stripe's metadata docs and Thexly's Stripe guide side by side, and noted where the trail from click to payment can break. Three things stood out:

1. Meta only tags the first page. Its help page says the parameter "is only applicable to the first product page", and if someone leaves and comes back organically later, "the URL parameter will be lost" (Meta help).

2. Stripe metadata doesn't travel on its own. Stripe's docs say "An object's metadata doesn't automatically copy to related objects" (Stripe docs). So the session has to go on the object you create at checkout.

3. Stripe lets you limit the key. Thexly's guide asks for two permissions and nothing else (Thexly Stripe guide).

Step 1: tag the ad clicks in Meta

Meta's help page describes it like this (Meta help):

1. Create or edit an ad in Ads Manager and go to Tracking for that ad.

2. Enter your parameters in the URL parameters field, or click Build a URL parameter.

3. Click Apply.

An illustrative example of what to enter: utm_source=facebook&utm_medium=paid&utm_campaign=spring-launch. Use a readable campaign name. Thexly shows the utm_campaign value exactly as it arrives, so a name is easier to scan than a number. Keep utm_source fixed and lowercase, like facebook. Thexly's source reports group by the exact text, so Facebook, fb and ig would each get their own row.

Two rules from the same page are good to know. Parameters in the URL parameters field override duplicates in the Website URL field. And Meta says that as of 1 January 2024 it may add some parameters to ad traffic automatically, including Campaign Source, Campaign Medium, Ad ID and Campaign ID.

Thexly reads the UTM tags and Meta's fbclid from the page URL when the visitor lands, and labels fbclid clicks as Meta. There's no Meta account to connect.

One setting to check: if your Thexly script has data-exclude-search turned on, it drops all UTM tags and click IDs such as fbclid, so Thexly can't tie those visits to your campaigns. Leave it off on any page your ads link to.

Step 2: connect Stripe

1. In Stripe, go to Developers → API keys and click Create restricted key.

2. Name it something you'll recognise, like "thexly-readonly".

3. Set exactly two permissions and leave everything else at None: Checkout Sessions: Read and Webhooks: Write.

4. Create the key and copy it straight away. Stripe only shows it once. It starts with rk_live_ (or rk_test_ in test mode).

5. Paste it into Thexly under Settings → Payments → Stripe.

The only thing Thexly writes to your Stripe account is its own webhook registration. The key has no write access to payments, customers or anything else.

Step 3: pass the session at checkout

Stripe Payment Links placed as links on your page: nothing to do. The script adds the visitor's session to the link before they click it.

Buttons or checkouts opened with JavaScript: the session isn't added for you. Call window.thexly.getSessionId() on the page and add it to the Payment Link yourself as client_reference_id before you send the visitor to Stripe.

Checkout Sessions you create on your server: pass the session as client_reference_id or in metadata.thexly_session_id.

Standalone Payment Intents you create on your server: pass the session in metadata.thexly_session_id. That's the only field Thexly reads on a Payment Intent.

People building this by hand land on the same field. One r/SaaS reply: "If you use Stripe Payment Links instead of own sign-up, tag them with client_reference_id" (r/SaaS, February 2026).

If you use metadata, Stripe's limits apply: 50 key-value pairs, keys up to 40 characters with no square brackets, values up to 500 characters. Stripe also says never to store sensitive information, such as bank or card details, in metadata (Stripe docs).

Subscriptions and renewals

When Thexly receives a renewal payment, it matches it to the session in the invoice or subscription's metadata.thexly_session_id. If that's missing, it can match through an earlier payment by the same customer, the subscription's history, or thexly.identify() if you call it after login. So for subscriptions, it helps to set metadata.thexly_session_id on the subscription when you create it.

Check it works

1. Open your own ad's destination URL with the UTM parameters added.

2. Check your Thexly dashboard. Your visit should show up within a few seconds (docs).

3. Make a test purchase through the same checkout, or wait for the first real one.

4. Confirm the payment appears with the campaign name from step 1.

If the payment shows up with no campaign, check step 3 first. A button or a server-built checkout without the session is the usual gap.

What Thexly does and doesn't do

Thexly matches each Stripe payment to the visit that led to it and credits one channel. You choose per website whether that's the channel that first brought the visitor in or the one that closed the sale (docs).

It doesn't send conversions back to Meta, and it doesn't change your ad settings. It doesn't pull spend from Meta either, so you bring spend from Ads Manager when you compare the numbers.

Want to see how far Meta's reported revenue sits from Stripe first? The platform vs payment gap calculator does it from three numbers. More on reporting: Facebook ads reporting and when Meta and Google both claim the same sale. There's a 14-day trial, no card needed.

FAQ

Questions & answers

Sources