Purchase events checked row by row against the billing table, with cash vouchers, instalments, refunds and currency handled explicitly.
About this service
Before I touch a tag, I take one month of purchase events and compare them row by row with your billing table. On the accounts I am usually called into, the gap runs between 4 and 11 percent, and it is never random. It is the OXXO voucher that never settled, the refund nobody sent back, the confirmation page that fired again on a reload, and the order that arrived in MXN into a property configured in USD.
The reconciliation is the deliverable:
Everything else follows from it. The query runs against your own system of record, whether that is Stripe, Mercado Pago, Conekta or an enrolment table, and it stays in your repository and runs monthly after I leave. A purchase number that cannot be checked against money collected is a number nobody in finance will ever defend, and the first meeting where marketing and finance disagree is the meeting where all of it stops being used.
When the purchase actually happens:
Payments in Mexico force a decision most plans skip. A cash voucher issued at OXXO settles up to three days later, and a real share of vouchers never settle at all. Firing purchase at voucher issue inflates revenue and teaches the bidder to buy people who do not pay, so the event fires on the settlement webhook carrying the original event time and the click identifier stored at checkout. Meses sin intereses separates the amount captured from the order value; one of the two goes to the platform, the plan records which, and it does not change mid-quarter. The same discipline applies to IVA and shipping. Which side of the line they fall on matters far less than never moving the line quietly, because every historical ROAS comparison depends on it.
Deduplication and the failure modes I test for:
One event_id shared between the browser event and the Conversions API, transaction_id set in GA4, and then the tests that find what review meetings never do: a hard reload of the confirmation page, the back button into it, a double submit on a slow connection, and the return leg of a 3DS challenge. Each of these produces a duplicate on most sites I inspect, and each is a different fix.
Refunds, chargebacks and reversals:
A refund event with the matching transaction_id, and a negative offline event to the ad platform. Chargebacks land 45 to 90 days after the sale and almost never reach the analytics layer at all, which is how a channel with a fraud problem keeps looking like the best channel in the account. The monthly reconciliation catches them because it reads from the ledger rather than from the tag.
Sector notes:
For education, the purchase worth bidding on is the enrolment with a cleared deposit, not the checkout submit, and instalment plans need the contract value and the collected value kept as separate fields. For a token-denominated sale, the conversion policy is written down once: price at fill, one source, stated in the plan. Failed transactions and reorganised blocks are not purchases and must not reach the event stream at all.
Not included:
Merchant Center and catalog feed work. Theme or storefront development. Attribution modelling. Dashboard building. Subscription revenue recognition, which belongs to your finance systems and not to a tag.
What I refuse:
Purchase fired on a page view of the thank-you URL. Any value the finance team has not signed off on. Replaying history that was never collected correctly, which produces a clean-looking series that quietly lies about the past.
Who this is not for:
Pre-revenue products, and teams who want reported revenue to rise. Reconciliation almost always moves it down before anything else improves.
Scope
- Target market
- Worldwide, Mexico, LATAM
- Working language
- English, Spanish
- Industry
- Ecommerce and DTC, Marketplaces, Crypto and Web3, Education and edtech
- Engagement model
- One-off project
- Turnaround
- 1 month or more
- Seller type
- In-house-grade specialist