Why am I seeing duplicate payments?
If you see the same payment appearing twice in your DataFast dashboard, don't panic — it's a common setup issue with a simple fix.
What's happening
DataFast has two ways to attribute revenue to your traffic sources:
-
Automatic (URL parameters) — When a customer completes a purchase, your payment provider (Stripe, LemonSqueezy, Polar) redirects them back to your website with a special parameter in the URL (like
?session_id=...). The DataFast script on your page sees this parameter and records the payment automatically. This is what happens when you set up Stripe Payment Links, LemonSqueezy Payment Links, or Polar Checkout Links. -
Server-side (metadata) — When you create a checkout session in your code, you pass the visitor's
datafast_visitor_idanddatafast_session_idas metadata. When the payment succeeds, DataFast receives the payment via webhook and attributes it using that metadata. This is what happens when you follow the Stripe Checkout API, LemonSqueezy Checkout API, or Polar Checkout API guides.
The problem: If you have both set up at the same time, the same payment gets recorded twice — once from the URL parameter when the customer lands on your success page, and once from the webhook on the server.
How to fix it
You have two options. Pick one, not both.
Option 1: Keep server-side, disable automatic (recommended)
Server-side attribution is more accurate because it works even if the customer closes the browser before the redirect, opens the success page on a different device, or has an ad blocker. We recommend this option if you have server-side set up.
data-disable-payments="true" to your DataFast script tag:<script
defer
data-website-id="dfid_******"
data-domain="your_domain.com"
data-disable-payments="true"
src="https://datafa.st/js/script.js"
></script>
That's it. The script will stop reading payment parameters from URLs. Your server-side attribution keeps working as before.
window.datafast("payment", { email }) calls still work when this is enabled. Only the automatic URL parameter detection is turned off. See script configuration for all available options.Option 2: Keep automatic, remove server-side
datafast_visitor_id and datafast_session_id metadata from your checkout session creation code. The automatic URL parameter method will continue working on its own.metadata object:// Before (server-side attribution enabled)
const session = await stripe.checkout.sessions.create({
// ...
metadata: {
datafast_visitor_id: cookieStore.get('datafast_visitor_id')?.value,
datafast_session_id: cookieStore.get('datafast_session_id')?.value,
},
});
// After (server-side attribution removed)
const session = await stripe.checkout.sessions.create({
// ...
// no metadata — automatic URL attribution handles it
});
Keep in mind that automatic attribution relies on the customer being redirected back to your site on the same device and browser. If they close the tab or the redirect fails, the payment won't be attributed.
Which option should I choose?
-
Server-side (option 1) is more reliable. Payments are attributed even if the customer never returns to your website after paying. If you already have server-side set up, keep it and just add
data-disable-payments="true"to your script. -
Automatic (option 2) is easier to set up since it doesn't require any code. But it only works when the customer actually lands on the redirect URL in the same browser.
data-disable-payments="true" to your script and you're done.Related documentation
- Revenue attribution guide — choose the right attribution method for your setup
- Script configuration reference — all script attributes including
data-disable-payments - Stripe Checkout API — server-side attribution for Stripe
- Stripe Payment Links — automatic attribution for Stripe
- LemonSqueezy Checkout API — server-side attribution for LemonSqueezy
- LemonSqueezy Payment Links — automatic attribution for LemonSqueezy
- Polar Checkout API — server-side attribution for Polar
- Polar Checkout Links — automatic attribution for Polar