Why Payment Link Emails Don’t Identify Customers
Resumo
Pixel’s announcement explains why a payment link’s payer_email may be a wallet-generated alias rather than a customer’s identity, while client_email is simply the address entered when creating the link. It highlights how email-based customer counts can split one person or merge several, and points to Stripe’s client_reference_id as a more reliable tracking option.
DEV Community
Your payment link's email field names the wallet, not the person
I spent 39 days reading one field wrong. The field was the payer email on a payment link, and it does not tell you which customer paid. What the receipt actually contains One $25 payment, one link, ten fields: status, title, amount, net amount, url, client email, created, paid, payer email, and a reversal field. (The platform I sell on wraps Stripe, so two fields are its own wrapper units. The two that matter are the Stripe ones.) There is no payment-method field and no wallet field. client_email: the address typed in when the link was created. In my case, the one I typed for the person I was sending the link to. payer_email: the address the wallet presented when the card was charged. sha256 of each, so no real address goes in this post: client_email 1140835cdb862c90d0b67ac1b39f5917c0c85ba6c88aba88f282ca233155cad8
payer_email 15ba2bffb49ebda0f048ab7b40236034e9c57ae4e306a913e09caed7d563b184
Not equal. Different domains. Longest shared run between the two strings: .com. The receipt cannot tell you why. So I asked the payer. She said it was her, Apple Pay generated the alias, and she has no idea what the alias string is. She remembered seeing it and laughing at it. That is the whole problem in one line: the person paid, and her wallet invented a new string for her on the way to my ledger. Two failures, opposite directions If you count customers by email, you get both of these: One person, many strings. Every wallet, phone, or browser that mints an alias splits one customer into several. Many people, one string. One card shared by a household or a team collapses several customers into one. Neither is fixed by collecting a cleaner address. The address is not an identity. It is a presentation detail of whichever wallet was in the room. The field that survives the wallet Stripe's own answer is client_reference_id. On a payment link you append it as a URL parameter: https://buy.stripe.com/xxxx?client_reference_id=customer_8812
It is your string, up to 200 characters, alphanumeric plus dashes and underscores. Invalid values are silently dropped, so print one back before you trust it. It rides the Checkout Session and comes back with the payment. If you create links by API, a metadata key does the same job. The rule I use now: never join payments to people by email. Join them to a string I control, written at the moment I created the link. Keep the email as a hint to show a human when they ask. A check you can run in five minutes Print both email columns side by side for your last twenty payments. Count distinct values in each. If the payer column has more distinct values than the client column, you are counting wallets. If it has fewer, you are counting households. Either gap is the bug, and neither shows up in a revenue total. I lost 39 days to a column nobody wrote. It cost nothing to fix once I stopped defending it. If you run the check and your last twenty payments don't reconcile, say so in the comments and I'll run it on your export and hand you the table. Twenty rows, five minutes, no charge for a first look. If it turns out you need a real fix, we talk then.

Powered by Readybot.io