Your Attribution Is Lying to You — Here's How to Fix It
The $500k Lie
Facebook says you made $500k from their ads. Google says $400k from theirs. Klaviyo claims $200k from email. That's $1.1M in attributed revenue — but your Stripe account shows $600k total.
Welcome to the attribution crisis. And it's costing you real money because you're scaling campaigns based on fictional numbers.
Why Attribution Breaks
The Double-Counting Problem
Every platform takes credit for every conversion it touched:
Customer journey:
1. Sees Facebook ad (Facebook claims credit)
2. Clicks Google ad (Google claims credit)
3. Opens email (Klaviyo claims credit)
4. Buys directly (Shopify attributes to direct)
Reality: 1 order, $100 revenue
Platform claims: 4 attributions, $400 "revenue"
The Pixel Problem
Client-side tracking is increasingly unreliable:
- iOS privacy changes block 40-60% of tracking
- Ad blockers prevent 25-30% of pixel fires
- Cookie restrictions break cross-session attribution
- Consent banners reduce tracking opt-in to 60-70%
The Lag Problem
Attribution windows don't match buying behavior:
- Facebook's 7-day click window misses the customer who researched for 3 weeks
- Google's last-click model ignores the 5 touchpoints before the final search
- Email attribution counts opens that didn't influence the purchase
The Fix: Server-Side Truth
Stop relying on platform pixels. Build server-side attribution:
// Server-side purchase tracking
async function trackPurchase(order: Order) {
// 1. Record the actual purchase with verified data
const purchase = {
orderId: order.id,
revenue: order.total,
currency: order.currency,
timestamp: order.completedAt,
customerId: order.customer.id,
};
// 2. Send to platforms via server APIs (not pixels)
await Promise.all([
sendToFacebookCAPI(purchase),
sendToGoogleOfflineConversions(purchase),
sendToKlaviyoServerSide(purchase),
]);
// 3. Record in YOUR attribution system as source of truth
await attributionStore.record({
...purchase,
touchpoints: await getTouchpoints(order.customer.id),
attributionModel: "data_driven",
});
}Facebook Conversions API (CAPI)
async function sendToFacebookCAPI(purchase: Purchase) {
await fetch(`https://graph.facebook.com/v19.0/${PIXEL_ID}/events`, {
method: "POST",
body: JSON.stringify({
data: [{
event_name: "Purchase",
event_time: Math.floor(purchase.timestamp / 1000),
event_source_url: purchase.sourceUrl,
user_data: {
em: hash(purchase.customerEmail),
ph: hash(purchase.customerPhone),
external_id: hash(purchase.customerId),
},
custom_data: {
currency: purchase.currency,
value: purchase.revenue,
order_id: purchase.orderId,
},
}],
}),
});
}The Attribution Model That Works
Forget last-click. Forget first-click. Use a blended model:
The Three-Number Framework
| Metric | What It Tells You | How to Calculate |
|---|---|---|
| Platform ROAS | What the platform claims | Platform reported revenue / ad spend |
| Blended ROAS | What actually happened | Total revenue / total marketing spend |
| Incremental ROAS | What the ads actually caused | (Revenue with ads - baseline) / ad spend |
The only number that matters is blended ROAS. If your total revenue divided by total marketing spend isn't profitable, it doesn't matter what any individual platform claims.
The Incrementality Test
The gold standard for attribution: turn things off and measure the impact.
Week 1-2: Baseline measurement (all channels running)
Week 3-4: Turn off Facebook prospecting
Week 5-6: Measure revenue change
If revenue drops 20% and Facebook was 30% of spend:
Incremental ROAS = Revenue drop / Spend saved
True Facebook contribution = 20% of revenue, not 50%
The Dashboard You Need
Daily Attribution Dashboard:
Revenue (Source of Truth: Stripe)
├── Total: $28,400
├── vs Platform Claims: $41,200 (1.45x inflation)
└── vs Yesterday: +12%
Blended Metrics:
├── Total Ad Spend: $8,200
├── Blended ROAS: 3.46x
├── Blended CAC: $34
└── New Customer Revenue: $12,800
Channel Performance (Server-Side):
├── Paid Social: $3,400 spend → $11,200 attributed (3.29x)
├── Paid Search: $2,800 spend → $9,600 attributed (3.43x)
├── Email/SMS: $400 spend → $5,200 attributed (13.0x)
└── Organic/Direct: $0 spend → $2,400
The Implementation Roadmap
Week 1: Audit Current State
- Compare platform-reported revenue vs actual revenue
- Calculate the "inflation factor" for each platform
- Identify which events are tracked client-side vs server-side
Week 2: Implement Server-Side Tracking
- Set up Facebook CAPI
- Set up Google Offline Conversions
- Implement server-side event tracking for all purchase events
Week 3: Build the Truth Dashboard
- Single source of truth for revenue (Stripe/payment processor)
- Blended ROAS calculation
- Channel-level server-side attribution
Week 4: Calibrate and Optimize
- Compare server-side vs client-side numbers
- Adjust platform bidding based on real ROAS
- Set up automated alerts for attribution drift
Stop Scaling Lies
Every dollar you spend scaling a campaign based on inflated attribution is a dollar wasted. Fix the measurement first, then scale what's actually working.
The companies that win at paid acquisition aren't the ones with the biggest budgets. They're the ones who know which dollars are actually working — and have the discipline to cut the ones that aren't.