Google Analytics will tell you that 4,000 people visited from LinkedIn last month. It will not tell you that three of them bought. This is not a configuration you have failed to enable or a report you have not found. It is a consequence of what the tool is and where it sits.
People spend weeks trying to fix this — adding goals, wiring up conversion events, reading forum threads about enhanced ecommerce — and come away with a number that is close but never trustworthy. Understanding why saves you those weeks.
Two systems that were never introduced
Your analytics lives on your website. It sees anonymous sessions: a device arrived, viewed three pages, came from a referrer, left. It has no idea who that was. Your money lives in Stripe. Stripe sees an email, an amount, a card, a subscription. It has no idea what pages that person looked at or where they came from.
Nothing carries an identifier from one to the other. The visitor crosses from your site into a hosted checkout, and at that boundary the analytics session ends and the payment record begins. They are two databases with no shared key, which in practice means no join is possible.
Every workaround you have read about is an attempt to fabricate that shared key. Some work partially. None of them come for free with the analytics tool, because the tool was designed to measure traffic, and traffic is genuinely all it can see.
Why the usual fixes fall short
The standard advice is to fire a purchase event on your thank-you page. This works in the sense that a number appears in the report. It is unreliable in several specific ways, and the failures all push in the same direction: undercounting, inconsistently.
- Not everyone lands on the thank-you page. They close the tab after paying, or the redirect fails, and the event never fires.
- Ad and tracking blockers stop analytics scripts. A meaningful share of a technical audience blocks them entirely, and those visits simply do not exist in your reports.
- The hosted checkout is a different domain. Unless cross-domain measurement is configured correctly, the return trip starts a new session attributed to the checkout provider rather than the original source.
- Refunds, failed payments, chargebacks and cancelled subscriptions do not fire a page load, so the analytics number drifts away from actual revenue over time.
- Analytics reporting applies its own modelling and thresholds. The revenue figure it shows you is an estimate, not a ledger.
The deeper issue is that even when it works, it tells you revenue by traffic source, not revenue by post. GA can say LinkedIn produced $600. It cannot say which of the eleven LinkedIn posts you published produced it, because every one of those posts pointed at the same link and arrived in the same bucket.
What a real join looks like
Closing the gap requires exactly one thing: a single identifier that travels from the click, through the visit, into the checkout, and back out on the payment record. Once both sides hold the same value, joining them is trivial.
The chain has four links. A tracked link stamps the click with an id specific to that post on that platform. A first-party cookie remembers it, so the visitor is still identifiable when they come back four days later. At checkout, the id is attached to the payment — with Stripe, client_reference_id on a Checkout Session or Payment Link is designed for precisely this. And when the payment completes, the webhook returns the id, and the sale now has a source.
Note what this does not require: no ad platform, no data warehouse, no machine learning. It is a foreign key. The reason it feels exotic is only that no single off-the-shelf tool spans both sides of the boundary, so somebody has to carry the value across it.
What Google Analytics is genuinely good at
This is not an argument for deleting it. GA is excellent at questions about behaviour on your site. Which pages do people land on. Where do they drop out of a signup flow. How long does the pricing page hold attention. Which blog posts bring search traffic and which ones bring traffic that leaves immediately.
Those are real questions and the answers change what you build. Keep the tool for them. Just stop asking it the revenue question, because the honest answer is that it does not have the data, and the numbers it produces when pressed will be an undercount of unknown size.
The clean division is this: analytics for what happens on your site, your payment processor for what happens to your money, and an attribution layer to connect the two. Trying to make one tool do all three jobs is what produces the weeks of frustration.
Building it versus buying it
You can build the chain yourself. A link shortener that logs clicks, a cookie, a bit of code that appends the id to your checkout URL, a webhook handler, and a table joining ids to posts. A capable developer gets a working version up in a couple of days.
The maintenance is the real cost. Every new post needs its own tracked link. Every platform needs its own variant of that link. Tokens expire, checkout flows change, and the whole thing degrades silently when one step is skipped, because a broken attribution chain does not throw an error — it just produces slightly wrong numbers forever.
seenpaid exists to be the wire between those two boxes. It publishes your posts to the networks you have connected, generates a distinct tracked link per post and platform automatically, carries the identifier through to your Stripe checkout, and reads your Stripe account read-only to match payments back to the post that produced them. Same mechanism as the build-it-yourself version, run consistently rather than when you remember.
The question worth answering
The point of all this is a single sentence that Google Analytics structurally cannot produce: this post, on this platform, produced this many dollars. Not sessions from LinkedIn. Not an estimated conversion count. Dollars that cleared, tied to a specific piece of content.
That sentence reorganises how you spend your time faster than any traffic report, because it usually contradicts your instincts. The platform you enjoy most is often not the one that pays. The post you were proudest of made nothing. The quiet reply you nearly deleted brought in three customers.
You cannot get there by configuring analytics more carefully. You get there by putting the same identifier on both sides of the boundary. It is a small technical idea with a large practical consequence, and it is the difference between measuring traffic and measuring a business.