Skip to content
pixelary Docs

Stripe

Webhook Paid plans

A thank-you page misses purchases: the customer closes the tab, the redirect fails, a browser blocks the pixel. With the Stripe webhook, Purchase comes from Stripe itself and goes to your pixels from our servers.

This works with Payment Links, Stripe Checkout, Buy Buttons and pricing tables. There is no Stripe Connect and no OAuth: you add one webhook in your own Stripe account, and Pixelary gets no access to anything else there.

1 Add the webhook in Stripe

In the Pixelary dashboard open your site and choose Stripe. Copy the webhook URL, which looks like https://api.pixelary.app/hooks/stripe/<site_key>.

In Stripe, open Developers → Webhooks → Add destination. Listen to events from your account with the snapshot payload, paste the URL, and select these events:

EventWhat Pixelary does
checkout.session.completedSends Purchase when the session is paid.
checkout.session.async_payment_succeededSends Purchase when a delayed payment, such as a bank debit, comes through.
invoice.paidSends Purchase for a subscription renewal, only with Count subscription renewals on.

2 Paste the signing secret

On the webhook's page in Stripe, reveal the signing secret. It starts with whsec_. Paste it on the Stripe screen in Pixelary. It is stored encrypted and never shown again. Only the site's owner can change it.

A test webhook and a live webhook have different secrets, and Pixelary keeps one per site. Set up the test webhook and test with it, then replace the secret with the live one. Events signed with the other secret are refused until you switch.

Once Stripe is connected, the Pixelary script on your site does the rest. For visitors who allow ad cookies, it adds their visitor ID to buy.stripe.com links as client_reference_id, and to <stripe-buy-button> and <stripe-pricing-table> elements as client-reference-id. It also tells Pixelary their ad click and browser IDs, so a purchase can match the ad that brought them. Pixelary keeps these for 7 days.

A link or element that already has a reference of yours stays as it is, and its purchases count as not linked. The same goes for Checkout Sessions you create with Stripe's API and Payment Links on a custom domain.

4 Make a test purchase

Stripe marks test events with livemode: false. They go only to test mode: the test event code on Meta and TikTok, and validation only on ChatGPT Ads. A pixel without a test event code is skipped, so a test purchase can never count as a real conversion. In Live events they appear with a Stripe test label, and the Stripe screen shows the last event received.

Avoid counting a sale twice

If a trigger on your thank-you page also sends Purchase, each sale counts twice: the webhook's copy and the trigger's copy have different event IDs, so the platforms cannot merge them. The Stripe screen warns you when an enabled trigger sends Purchase. Turn that trigger off once test purchases show up in Live events. If you send Purchase from your own code, remove that too.

A redelivery from Stripe never counts twice. Pixelary remembers each event and session it has handled, and the event ID sent to the platforms comes from the Stripe session.

A webhook has no browser, so nobody can ask the customer at that moment. What Pixelary does depends on whether the purchase matches a visit that recorded an answer:

PurchaseWhat happensWhat is sent
Matches a visit, ad data allowedSentAd click and browser IDs, IP address and user agent from the visit; hashed email and phone
Matches a visit, ad data refusedNot sentNothing, whatever your settings say
Link from a visitor who refused ad cookiesNot sentNothing, whatever your settings say
No matching visit, customer outside the EEA, UK and SwitzerlandSentHashed email only
No matching visit, customer in the EEA, UK or Switzerland, or country unknownNot sentNothing, unless you turn on the setting below

"Country" here is the billing country Stripe reports. A purchase has no matching visit when the customer opened the link somewhere else, such as an email, or paid more than 7 days after the click. Purchases not sent stay in Live events with the reason, so nothing disappears without a trace.

Send purchases we can't link to a visit

This setting, off by default, also sends purchases with no matching visit from the EEA, the UK, Switzerland and unknown countries, with the email hash only. Nobody asked these customers for consent on your site, so you are responsible for having a legal basis to share this data with ad platforms. A visitor who refused ad data is still never sent.

What counts as a purchase

  • The value is the session's total in its currency, with zero-decimal currencies such as JPY handled.
  • A free trial or a fully discounted order is not a Purchase, because nothing was paid. Live events shows it as not sent.
  • A renewal is not a Purchase unless you turn on Count subscription renewals. Renewals have no visit, so the rules for purchases with no matching visit apply.
  • Your filters still apply: excluded countries and "only conversions from ad clicks" stop a purchase like any other event.
  • Each purchase counts as one server event on your plan. Test events count too.

What is kept

  • Stripe sends the customer's email, phone and billing address to our servers. Email and phone are hashed for each platform and go no further. Pixelary does not store them, or Stripe's payload, and the event log shows only the names of the matching fields.
  • Pixelary keeps what a visitor allowed, with their ad click and browser IDs, IP address and user agent, for up to 7 days in the EU, and deletes it when the purchase uses it.
  • Add this to your own privacy policy: tell customers that purchase data goes to the ad platforms you use.

If nothing arrives

  • Stripe's webhook page lists each delivery with its response. A 400 means the secret on the Stripe screen is not this webhook's secret, or none is saved.
  • Stripe retries for up to 3 days when a delivery fails, and Pixelary answers with an error when every one of your pixels refused the event, so a short outage at a platform loses nothing.
  • Make sure the destination uses the snapshot payload. Pixelary ignores thin events.

Consent & banners

Something here doesn’t match what you see? Write to hello@pixelary.app.