Best analytics tool I've used in 14 years

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:

  1. 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.
  2. Server-side (metadata) — When you create a checkout session in your code, you pass the visitor's datafast_visitor_id and datafast_session_id as 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.

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.

Add 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

If you don't want to touch your code and prefer the no-code approach, remove the 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.
For example, if you followed the Stripe Checkout API guide, you would remove the 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.

TL;DR — If you've already set up server-side attribution, go with option 1. Add data-disable-payments="true" to your script and you're done.
Something missing? Suggest features ✍️