ReferralFlo
Engineering·Sep 1, 2026·8 min read

Stripe-Shopify Integration: Reconciling Referral Conversions

Stripe Shopify integration mismatches break referral attribution: this guide shows how to reconcile conversion records with webhooks and the REST API.

NANaveed Ahmer
Naveed Ahmer
Referral Strategy Consultant
Share
Editorial photograph: Over-the-shoulder view of a desk at dusk, two monitors showing scrolling terminal logs, a coffee mug and a notebook with handwritten arrows connecting two columns of numbers.

A Stripe Shopify integration mismatch usually means the two systems never shared a common ID for the same customer. Stripe tracks payments by customer ID and billing email. Shopify tracks orders by customer ID and checkout email, which can differ after a guest checkout or a payment method swap. Reconciling referral conversions means building one identity key both systems can match against, then resolving each event against that key with webhooks and the REST API.

Why Stripe and Shopify disagree about the same referral

Stripe and Shopify disagree about a referral conversion because each platform assigns its own customer identifier, and neither ID is designed to match ReferralFlo's referral link token. A shopper can check out as a guest in Shopify under one email, then have Stripe generate a customer object under a different email captured at a later subscription renewal.

A few common causes show up repeatedly:

  • Guest checkout in Shopify creates an order without a persistent Shopify customer account, so the email on the order can differ from the email later used to pay via Stripe Billing.
  • Payment method email vs. account email: a buyer's card is registered under a work email in Stripe, but their Shopify account uses a personal email.
  • Upgrades and plan changes in Stripe can spin up a new customer object rather than updating the existing one, splitting the payment history in two.
  • Multi-store or multi-region Shopify setups issue separate customer records per storefront even for the same person.

None of this is a bug in either platform. Stripe and Shopify solve payments and commerce, not cross-system identity resolution. That's the job the reconciliation layer has to do.

Build a canonical identity key before matching anything

A canonical identity key is a single deterministic value, typically a hashed, lowercased email plus the referral token captured by ReferralFlo's Growth Graph, that both Stripe and Shopify events get mapped to before comparison. Comparing Stripe's customer.id directly against Shopify's customer_id compares two arbitrary strings that were never meant to line up.

The Growth Graph already does cross-domain attribution with device fingerprinting and UTM passthrough, so the referral token is available at click time, before either checkout ever fires. That token, not either platform's internal ID, is the anchor for the key.

Field Stripe Shopify ReferralFlo Growth Graph
Identifier customer.id customer_id / order.id referral link token
Email source billing email on PaymentMethod or Customer object checkout email or account email UTM passthrough + device fingerprint
Event of interest checkout.session.completed, invoice.paid orders/create, orders/paid referral conversion webhook
Typical timing at payment capture at order creation, sometimes before capture across the click-to-conversion window

Diagram showing Stripe and Shopify events merging through a hashed-email-and-token match key into one unified referral record.

Once the key exists, both webhook payloads get normalized against it before anything is written to a permanent record. Skip this step and you'll spend more time debugging phantom duplicate conversions than you saved by wiring the integration quickly.

Reconcile with webhooks and the REST API

Reconciling referral conversions between Stripe and Shopify is a five-step pipeline: subscribe to both platforms' webhooks, normalize identity fields into the canonical key, write matched events to a resolution table, poll the REST API for anything the webhooks missed, then push the resolved status back into the Growth Graph so rewards can fire.

  1. Subscribe to source webhooks. Register checkout.session.completed and invoice.paid in Stripe, and orders/create and orders/paid in Shopify, per Stripe's webhook documentation and Shopify's webhook documentation.
  2. Normalize identity fields on arrival. Lowercase and hash the email on each payload, then attach the referral token pulled from the click-tracking cookie or the order's landing-page UTM parameters.
  3. Write to a matching table keyed by the canonical identity. Each row holds the hashed email, the referral token, the Stripe event ID, and the Shopify order ID once both arrive.
  4. Poll the REST API for stragglers. Webhooks can be delayed or dropped during platform incidents. A nightly job against Stripe's /v1/events and Shopify's /admin/api/orders.json catches anything the webhook listener missed.
  5. Push resolved status back into the Growth Graph. Once a row has both a Stripe and a Shopify entry under the same key, mark the referral conversion resolved and release any reward held in escrow pending that event.

Most of the engineering effort lives in step 2. Get normalization wrong and every downstream step compounds the error instead of fixing it.

Worked example: reconciling a mismatched referral conversion

Here's an illustrative walkthrough for a DTC beauty brand running Shopify for storefront orders and Stripe Billing for subscription reorders. The numbers below are assumptions for the example, not observed data.

Assume a customer clicks a referral link, lands on the storefront, and completes a first order as a guest checkout using a personal Gmail address. Two months later they set up a subscription reorder, and Stripe captures the payment method under a different address tied to their work account.

Record Source Email Amount Referral token
Order 1 Shopify orders/create personal Gmail address $68.00 rf_9x2k
Subscription charge Stripe invoice.paid work email address $68.00 (missing, not passed by Stripe)

Without a canonical key, these look like two unrelated customers. With the key, resolution works because the Shopify order carried the referral token in its landing-page UTM parameters, which the Growth Graph captured at click time and stored against the device fingerprint. When the Stripe invoice event arrives without a token, the matching table checks the device fingerprint and billing metadata against the same fingerprint record from the original session, links it to rf_9x2k, and writes both events into one resolved row.

On a double-sided reward of $10 for the referrer and 15% off for the referred customer, that resolution is what triggers the payout. Skip the fingerprint fallback and the second charge, worth $68 in recurring revenue, never gets attributed, and the referrer never gets paid for a conversion they earned.

Edge cases that break naive matching

Even a well-built matching table breaks under a handful of predictable conditions: refunded orders that reverse a resolved conversion, shared household emails that collapse two buyers into one record, disposable emails at guest checkout, and test-mode events leaking into production data. Each requires explicit handling in the reconciliation logic, since trusting the matching table alone lets these cases slip through silently.

  • Refunds and chargebacks. A Stripe refund event should reverse an already-resolved conversion, not simply get ignored. Otherwise a refunded order still shows as a paid referral in your dashboard.
  • Shared household emails. Two people ordering under the same email will look like duplicate conversions from one buyer. Device fingerprinting from the Growth Graph, not email alone, is what separates them.
  • Disposable or throwaway emails at guest checkout. These are exactly the pattern ReferralFlo's anti-fraud detection flags for self-referral and disposable-email abuse, and reconciliation logic should route them to review instead of auto-resolving.
  • Test-mode data leaking into production. Stripe test-mode events and Shopify draft orders should never enter the matching table; filter on environment before normalization, not after.

If fraud patterns and reconciliation logic overlap in your pipeline, it's worth reviewing the anti-fraud checklist for referral programs alongside this one, since disposable-email detection and identity reconciliation often need to run against the same event stream.

Where reconciliation fits into your attribution stack

Reconciliation isn't a one-off script. It's the layer that lets ReferralFlo's Growth Graph tie referrals to conversions across every connected system, including Stripe, Shopify, and HubSpot, without relying on any single platform's internal ID as the source of truth. Get the canonical key right once, and every future integration inherits it.

The same pattern applies outside e-commerce. A field-services business tying referral payouts to a completed job, instead of only a signed contract, faces the identical problem of two systems disagreeing on when the real conversion happened; see how one program ties payouts to completed installs for a non-payments version of the same reconciliation logic.

Every resolved and unresolved row should also land in an immutable, cryptographically signed audit log, both for debugging and for defending payout decisions later. Full setup details, including webhook payload schemas and REST API rate limits, are in the integration docs, and the integrations hub lists exactly which Stripe and Shopify events are supported out of the box. If you're still scoping the build, the ROI calculator is a faster way to check whether the engineering time is worth it before you write the first line of the matching table.

Frequently asked questions

How do I match a Stripe customer to a Shopify customer for referral attribution?

Build a canonical identity key from a hashed email plus the referral token captured at click time, then normalize both Stripe and Shopify webhook payloads against that key before comparing them.

What should I do when Stripe and Shopify show different emails for the same buyer?

Fall back to device fingerprinting or billing metadata to link the records, since email alone won't resolve cases where a guest checkout email differs from a later billing email.

Do Stripe and Shopify customer IDs need to match for referral tracking to work?

No. Neither platform's internal customer ID is designed for cross-system matching; a shared identity key built from email hashes and referral tokens is what makes reconciliation work.

How do webhooks help reconcile referral conversions between Stripe and Shopify?

Webhooks deliver events like checkout.session.completed and orders/paid in near real time, letting a matching table normalize and link them under one identity key as they arrive, instead of waiting for a batch export.

NANaveed Ahmer
Naveed Ahmer
Referral Strategy Consultant

Referral program specialist and researcher who helps businesses turn referrals into a stable, scalable, and transparent distribution channel.

17 articles by this author →
Built for engineers

Fraud checks you don't have to build.

Device fingerprinting, IP velocity limits, disposable-email blocking and reward escrow — all built in.

Related reading