Confirm conversions from Stripe
Last updated Nov 9, 2026
Have Stripe confirm each payment to TraceLog through a signed webhook. TraceLog doesn't connect to your Stripe account and reads nothing from it.
What it does
When someone pays through Stripe, Stripe itself tells TraceLog. That notice doesn't depend on the page or on Google Tag Manager, so it still arrives if either one fails.
A one-off payment, the first payment of a subscription and a delayed payment that succeeds all count. Refunds, renewals and test payments don't.
Of each notice, TraceLog keeps the identifier and the time: no name, email or amount.
Set it up
Open Installation and keys in your project, choose Set up under Confirm conversions from Stripe, then:
- In Stripe, open Webhooks in Workbench and choose Create an event destination, then Your account.
- For the payload format, choose Snapshot. Stripe recommends Thin, but Thin carries nothing TraceLog can confirm. Leave the API version as it is.
- Select
checkout.session.completed,checkout.session.async_payment_succeededandpayment_intent.succeeded. - Choose Webhook endpoint and paste the address TraceLog gives you as the Endpoint URL.
- Choose Reveal secret and paste the signing secret into TraceLog.
The address has this form: https://api.tracelog.io/v1/platforms/stripe/webhooks/:endpointId.
Send the identifier
Each payment has to carry the identifier your page sends, such as the order number.
| How you take the payment | Where the identifier goes |
|---|---|
| Checkout, hosted, embedded or with the Payment Element | client_reference_id, or metadata[tracelog_identifier], when the session is created |
| A Payment Link | ?client_reference_id=<identifier> on the link: letters, digits, dashes and underscores, up to 200 characters |
| Your own form, on the Payment Intents API | metadata[tracelog_identifier] on the PaymentIntent |
| A subscription through Checkout | On the session, as for a single payment. Not in subscription_data.metadata: it doesn't reach TraceLog. |
| A subscription on your own form | metadata[tracelog_identifier] on the first payment's PaymentIntent. Renewals don't need it. |
For Checkout:
await stripe.checkout.sessions.create({
mode: "payment",
client_reference_id: order.number,
// line items and URLs
});For a Payment Link:
https://buy.stripe.com/your-link?client_reference_id=order-1042For your own form:
await stripe.paymentIntents.create({
amount: order.total,
currency: order.currency,
metadata: { tracelog_identifier: order.number },
});For a subscription through Checkout, on the session, as for a single payment:
await stripe.checkout.sessions.create({
mode: "subscription",
client_reference_id: order.number,
// line items and URLs
});For a subscription on your own form, set it on the first payment's PaymentIntent:
await stripe.paymentIntents.update(firstPaymentIntentId, {
metadata: { tracelog_identifier: order.number },
});Use the identifier your page sends with the conversion, one for each order,
never a person's email. An identifier that is blank, longer than 256 characters
or holds @ confirms nothing.
What you'll see
The conversion's count says who saw it: the server only, or the browser and the server when the page sent the same identifier.
The section in Installation and keys shows one status:
- Secret mismatch. Stripe's notices don't match the signing secret. Copy the destination's secret again.
- Wrong format. The destination sends Thin. Create one in Snapshot.
- Test mode. The notices come from a sandbox or test mode. Create a destination in live mode.
- Conversion gone. It is no longer in your conversion path. Choose Remove and set up Stripe again for the new conversion.
- Last confirmed payment, with its date.
- Notices arriving. Notices come in, but none has confirmed a conversion.
- No notice yet. The first arrives with the next payment.
TraceLog keeps no amount from Stripe, so a conversion's value is the one your page sends.
If you take other payments
Only payments through Stripe are confirmed; for the rest, TraceLog has only what the browser saw. Stripe confirms one conversion per project.