Attribution v1 — operating manual

The one-line goal. Trace every dollar back to the specific piece of content that started the journey, so the content pipeline becomes data-driven instead of opinion-driven.

Where this lives. Built into The Comms Dept Firebase app — extends the existing churches collection with an attribution map and a touches subcollection. See decisions (none yet) and the spec at the-comms-dept/docs/specs/attribution-v1.md for the technical writeup.

What it does, in plain English

Every audit submission is now stamped with a record of how the church got here:

  • Where they came from the FIRST time they hit any of our domains (utm_source_first, captured 90 days back)
  • Where they came from the LAST time before submitting (utm_source_last, the click that closed the loop)
  • What they self-reported on the form (“How did you hear about us?” dropdown)
  • Click IDs from paid ads (gclid / fbclid / ttclid) if present

Then every revenue event — Nucleus first-bill (mirrored from the V2 spreadsheet) or The Comms Dept Stripe upgrade — gets recorded as a touches entry on the same church doc. Nightly at 02:00 ET, a rollup function computes which content pieces drove the revenue.

The dashboard at admin.thecommsdept.com/attribution shows the same revenue ranked three different ways side-by-side:

  • First-touch ranking — credits the entry-point content
  • Last-touch ranking — credits whatever closed the loop
  • HDYHAU ranking — credits the self-report

When the three rankings agree, you have high-confidence attribution. When they disagree, the dashboard’s conflict feed surfaces those churches for manual investigation — usually the right answer is obvious within 30 seconds of looking at the church’s full touches timeline.

The two revenue paths

PathPayment systemConversion signalTouch type
Makeover first-bill (Nucleus Standard or Complete)Nucleus’s own platform — non-StripeFirst Bill date filled in V2 spreadsheet column Tspreadsheet_active
The Comms Dept upgrade (Pro-tier subscription post-makeover)Stripecheckout.session.completed / invoice.paid webhook eventscheckout_complete, invoice_paid

Both produce touches entries on the same church. The rollup function reads both types when computing window revenue.

How to read the dashboard

admin.thecommsdept.com/attribution

Window selector

Top of the page: 7 days / 30 days / 90 days. Default 30. Each window has its own pre-computed rollup doc — switching is instant.

Headline strip

  • Total revenue — sum of all conversion-event amounts in the window
  • Churches converted — count of unique churches with at least one revenue event
  • Avg revenue / church — total / churches
  • Top piece (U-shaped) — the single best-performing content piece using the U-shaped 40/40/20 model

Three rankings

The same revenue split three ways:

  • First-touch column: 100% credit to the entry-point content. Best for “what’s bringing new audits in?”
  • Last-touch column: 100% credit to whatever closed the loop. Best for “what made them finally submit?”
  • HDYHAU column: 100% credit to self-report. Best ground-truth signal — humans remember the YouTube video, not the UTM.

U-shaped attribution table

Below the three columns: a single ranking using a 40% first / 40% last / 20% middle credit split. This is the headline ranking when forced to pick one model. Use it for “rank our content portfolio by attributed dollars.”

Conflict feed

Churches where the three signals disagreed. Click into a church → see the full touches timeline → decide which signal to trust. If you decide the auto-detected source is wrong, edit the attribution on the church detail page (writes attribution.manualOverride — the next nightly rollup respects it).

Per-channel rollup

A grid of UTM sources with their total revenue. Useful for “which channels are we actually getting traffic from?”

Per-church attribution timeline

Every church detail page has an Attribution section showing:

  • Inferred source — the weighted-vote winner across signals, with confidence %
  • Three signal cards — what HDYHAU said, what first-touch UTM was, what last-touch UTM was
  • Touches timeline — chronological list of every observable event on this church’s path:
    • 🟡 form_submit — they submitted the audit
    • 🟢 spreadsheet_active — Nucleus first-bill cleared (revenue!)
    • 🟢 checkout_complete — The Comms Dept upgrade purchased via Stripe
    • 🔵 invoice_paid — recurring renewal (LTV signal)
    • 🔴 cancelled — subscription cancelled

Each entry shows the timestamp + revenue amount + product + UTM/referrer if known.

When to act on the data

  • Before: “What should we make this month?” (opinion-driven)
  • After: “Last month’s top performer drove $X. Why? What’s the next iteration of that?” (data-driven)

Specific moves the dashboard should drive:

  • Skill / format prioritization — which Brady-voice formats convert
  • Audience digest weighting — comments + DMs from churches that converted weigh more than non-converters
  • Ad spend reallocation — if YouTube drives 5x the revenue per audit of TikTok, shift production toward the higher-yield format
  • Hero piece selection — when picking the weekly YouTube hero, lean toward topics historically linked to high-LTV conversions

What this requires you to do as content gets made

For attribution to actually capture signal, every link from your content to your sites needs a UTM tag. Without UTMs, all the data shows is direct/none for organic traffic — you can see that someone converted, but not what brought them in.

See utm-tagging for the canonical taxonomy + best practices + a copy-pasteable cheat sheet.

Open / future work

  • Stripe Checkout metadata stamping — when The Comms Dept upgrade purchase flow gets built in the codebase, every stripe.checkout.sessions.create() call needs to include metadata: { churchId, firstSource, hdyhau, product } and client_reference_id: churchId. Without this the webhook falls back to email-matching which works but isn’t bulletproof.
  • Paid attribution — gclid/fbclid/ttclid are already captured in the touches subcollection but the dashboard doesn’t have a paid-spend ROI view yet. v2 work.
  • prochurchtools.com — out of scope for v1 (no funnel hooks back to our system yet). When that gets wired up, install the same GTM tag there.
  • v2 makeover existing-customer tracking + dashboard section. New requirement on the same Firebase app: a Firestore mirror of the Existing Users Google Sheet (ID 1XOoKxLcL0bYFghFsMVHWyCjYDysHvasm5cM0KlN2Vfw), 15-min cadence, that flows seven fields onto each church doc — isExistingNucleusCustomer, existingPlanMrr, hadV1Makeover, v2EligibilityOutcome, requiredCommitmentTier, commitmentCapturedAt, planAtDelivery. Plus a dashboard section that surfaces existing-customer upgrades (existing → Complete) separately and applies net-MRR accounting (count $100 deltas, not $199 gross) so reporting doesn’t inflate new-MRR claims. No Cloud Function for email-exact lookup at audit submission — detection is self-identification via the secondary CTA on Screen 8 of the makeover sign-up modal, with team validation and manual entry into the Existing Users sheet. Full spec at v2-eligibility-and-tracking. The Attribution v1 dashboard is the natural place for this section — same app, same Firestore — but it’s distinct from attribution proper (it’s a fulfillment-and-MRR view, not a touch-attribution view).
  • Spec: the-comms-dept/docs/specs/attribution-v1.md
  • Implementation README: the-comms-dept/playbooks/attribution/README.md
  • GTM tag JS: the-comms-dept/playbooks/attribution/pct-attribution-v1.gtm.js
  • This doc (operating manual): ~/iCloud/company-os/playbooks/attribution/README.md
  • UTM tagging guide: ~/iCloud/company-os/playbooks/attribution/utm-tagging.md
  • Dashboard: https://admin.thecommsdept.com/attribution