Paid acquisition engine: Judge every ad by the customers it brings in, not the clicks.
A creative wall of every ad across Meta and Google with spend, cost per acquisition, hook rate and status on each card, plus a fatigue check before anything is paused. Shown as the workspace for Ember & Oat, a direct-to-consumer coffee subscription.
The problem
Advertising platforms report their own conversions, while sales and payments live elsewhere. Creative-level performance becomes unreliable when UTMs disappear, leads cannot be matched or a platform conversion is treated as collected revenue. The system is designed to reconcile spend, creative exposure, CRM progression and first payment while preserving unmatched and unattributed records.
How the system is built
- SourcesLinkedIn, Meta and Google Ads; GTM/GA4 events; HubSpot; Stripe.
- IngestionDesigned hourly advertising pulls, lead webhooks and Stripe event delivery.
- NormalizationStable creative IDs, currency, account timezone and identity mappings.
- StoragePostgres daily creative facts, touchpoints, leads and payment ledger.
- DecisionsAttribution, fatigue flags, reconciliation and approval requirements.
- DashboardCreative-to-payment funnel with source and reconciliation detail.
- Write-backsApproved HubSpot attribution properties and operator-created optimization tasks.
The dashboard
13 views: Today, Founder summary, Comments and messages, Subscriber replies, Ad creatives, Campaigns, Audiences, Landing pages, New subscribers, Churn saves, Cohorts, Spend forecast, Reporting.
The creative wall: a gallery of the brand's ads rendered as they appear in feed and search, ranked by cost per acquisition, with spend, hook rate, ROAS and a scaling, testing or fatigued status on each one.
State lives in the URL (view, filters, date range), records open in drawers with their history, and every action that changes something is written to an activity log and is safe to repeat.
Data model
ad_creatives(id, platform, account_id, campaign_id, external_id)ad_daily(id, creative_id, date, spend_cents, impressions, clicks)touchpoints(id, anonymous_id, creative_id, occurred_at, consent_state)leads(id, crm_id, contact_key, created_at, match_state)identity_links(id, anonymous_id, contact_key, evidence)payments(id, stripe_id, customer_id, amount_cents, status)attributions(id, lead_id, touchpoint_id, model_version)exceptions(id, entity_id, reason, owner_id).
Rules in the backend
- Proposed reporting attribution: last eligible paid click within 30 days before lead creation; retain first touch separately.
- Match identities only through deterministic evidence; do not force unmatched leads into a campaign.
- Count first payment once per customer from a successful, non-zero Stripe collection; show later refunds separately.
- Proposed fatigue flag: trailing seven-day CTR falls at least 20% against the preceding seven days, with 1,000 impressions in each window.
- Fatigue flags create review tasks, not automatic budget changes.
Storage
Recommend Supabase Postgres with tenant RLS. Retain raw provider payloads for 30 days, attribution evidence for 13 months and financial records according to accounting requirements. Store Stripe identifiers, not card details; mask personal emails.
Reliability
Re-fetch the previous seven reporting days to capture platform revisions. Deduplicate payment events, use idempotent CRM writes and quarantine malformed rows. Show provisional totals, unmatched counts, failed imports and source-specific “Synced” timestamps.
Security and access
Use scoped OAuth credentials server-side. Analysts inspect performance; approvers authorize changes; clients receive read-only reporting. GTM deployment and advertising-account mutations require separate permission.
Cost
Advertising spend is separate from software costs. Reporting API access, connector subscriptions, database usage and event volume may add charges; no acquisition-cost improvement is claimed.
Use it
The window above runs the full workspace. Pause the tour and click through it, or open it full screen.
Technology stack
Meta AdsGoogle Ads
Tag Manager
GA4
Webflow
Stripe
Customer.io
Source & context
Designed and built by Ahmad Bukhari in November 2026.
The working interface represents creative-level reconciliation; live collection, consent configuration and payment matching remain designed integration work.
Built: 2026-11-03
Map a workflow like this
Start with the handoffs your team already runs and where they break.