foco
Back to Blog
The Attribution Window Mismatch: How Standard BI Infrastructure Killed a 4.2x ROAS Channel

The Attribution Window Mismatch: How Standard BI Infrastructure Killed a 4.2x ROAS Channel

December 28, 2025 5 min read

We killed a $45,000 CTV campaign on Day 9. The dashboard showed 0.09x ROAS. Leadership wanted the budget reallocated to retargeting, which was showing 2.1x.

Six weeks later, we discovered the CTV campaign had actually generated $115,000 in revenue. The real ROAS was 2.56x. We'd killed our best-performing channel because our measurement stack couldn't see past 7 days.

The setup

Veterinary equipment manufacturer. $1,200 automated prescription dispensing system. Average sale cycle: 45-60 days from initial awareness to PO approval. Target buyer: practice managers controlling 500-2,000 units across multiple clinic locations. LTV: $47,000.

The existing BI stack defaulted to 7-day attribution windows because that's what the Google Ads API and Meta CAPI returned natively. The executive dashboard was inherited from a prior B2C product line with same-day purchase behavior.

Nobody had changed the attribution window when the product changed.

This is a measurement architecture failure, not a strategy problem

Standard attribution infrastructure is built for transactional e-commerce with 24-48 hour conversion cycles. When you run it against B2B sales with 30-90 day decision windows, it systematically kills your best channels.

What the dashboard showed

We launched a CTV campaign via The Trade Desk targeting veterinary practice decision-makers across 12 DMAs. Week 1: 2.3M impressions, 14,000 estimated decision-makers reached. Attributed revenue in the 7-day window: $4,200. Dashboard ROAS: 0.09x.

We killed it and moved the remaining $32,000 to Meta retargeting. Retargeting showed immediate "success": 2.1x ROAS, 8.7% add-to-cart, 0.4% purchase conversion.

What we didn't see: 87% of those retargeting conversions came from users who had already engaged with sales reps or requested quotes directly. We were paying $180 CPA to intercept our own organic pipeline.

Meanwhile, the CTV campaign we'd killed had seeded 340 demo requests that converted over the next 6 weeks. The adstock decay curve told the real story:

  • Week 1: $4,200
  • Week 2: $18,900
  • Week 3: $31,400
  • Week 4: $28,700
  • Week 5: $19,200
  • Week 6: $12,800
  • Total: $115,200 — actual ROAS: 2.56x

How we fixed it the next time

Six months later, different client, similar problem. This time I built the measurement first.

Geo-based incrementality design

Split 24 comparable DMAs into treatment (CTV) and control (suppressed). 60/40 split — the CFO wouldn't accept 50/50 revenue risk. 8-week flight to capture 85% of the historical conversion window.

Custom attribution with adstock modeling

Built a Bayesian MMM using PyMC3 with geometric adstock decay (12-day half-life from historical cohort analysis), logistic saturation curves, and informed priors from B2B CTV benchmarks (typical ROAS range: 1.8x-4.5x).

adstock_rate = 0.6  # 60% retention week-over-week
saturation_point = 85000  # Spend level where returns diminish

transformed_spend = apply_adstock(raw_spend, decay=adstock_rate)
saturated_spend = apply_saturation(transformed_spend, alpha=saturation_point)
predicted_revenue = baseline + (coefficient * saturated_spend)

Reporting layer rebuild

Replaced GA4's 7-day default with custom BigQuery views that aggregated conversions across 90-day windows, used position-based attribution (40% first-touch, 40% last-touch, 20% distributed), and separated assisted vs. last-click revenue to flag retargeting cannibalization.

The results

Geo-holdout after 8 weeks:

  • Treatment DMAs: 127 conversions
  • Control DMAs: 41 conversions (68 expected when scaled to equivalent population)
  • Incremental lift: 59 conversions attributable to CTV
  • Incremental revenue: $247,000
  • CTV spend: $58,000
  • True incremental ROAS: 4.2x
  • CAC: $983 (well below $8,500 ceiling)

If we'd maintained the original strategy — kill CTV, double down on retargeting:

  • Estimated retargeting spend: $90,000
  • Incremental conversions: ~12 (89% cannibalization rate from incrementality test)
  • Incremental revenue: $50,400
  • Actual ROAS: 0.56x
  • Opportunity cost: $196,600 in foregone revenue

What I'd do differently today

Build attribution windows into the BI layer from day one. Default to 90-day lookback for anything over $500 AOV. Use Meta's Robyn or Google's Meridian instead of custom — faster stakeholder buy-in. Implement geo-holdouts as standard practice for any brand awareness channel.

The right KPI wasn't "ROAS in Week 1." It was cost per qualified enterprise demo measured at 45 days, and pipeline velocity of CTV-exposed accounts entering sales conversations within 60 days.

And the most important fix: pre-commit to measurement windows in writing before the campaign launches. "We will evaluate this channel at 8 weeks, not 8 days. Here's the power calculation showing why." Without that commitment, Week 1 panic kills the channel before the curve materializes.

The broader lesson

Most marketing teams aren't failing because they pick the wrong channels. They're failing because their measurement infrastructure makes long-term channels look like short-term failures.

If your BI stack defaults to 7-day attribution, you will systematically overinvest in retargeting (cannibalization masked as performance), underinvest in brand and awareness (delayed conversions appear as zero ROAS), and optimize for harvesting existing demand instead of creating new demand.

The fix isn't better media buying. It's better measurement architecture.

Still forcing long-lag channels into short attribution windows?

Get a measurement review

Share this article