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.

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 |

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.
- Subscribe to source webhooks. Register
checkout.session.completedandinvoice.paidin Stripe, andorders/createandorders/paidin Shopify, per Stripe's webhook documentation and Shopify's webhook documentation. - 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.
- 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.
- Poll the REST API for stragglers. Webhooks can be delayed or dropped during platform incidents. A nightly job against Stripe's
/v1/eventsand Shopify's/admin/api/orders.jsoncatches anything the webhook listener missed. - 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 | 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.

Referral program specialist and researcher who helps businesses turn referrals into a stable, scalable, and transparent distribution channel.
17 articles by this author →Fraud checks you don't have to build.
Device fingerprinting, IP velocity limits, disposable-email blocking and reward escrow — all built in.
Related reading

A Practical Anti-Fraud Checklist for Referral Programs
A referral fraud prevention checklist for engineers: self-referral detection, IP velocity limits, disposable e…


Tie HVAC Referral Payouts to Completed Installs
How to structure an HVAC referral program so rewards trigger on completed installs, not submitted leads, using…

