Total Spend
$11.01k
this period
Conversions
1,156
total events
Avg CPA
$9.53
cost per action
Impressions
2.0M
total reach
Brand Awareness — Q2 2025
Search · Last updated 2h ago
$3,240
/ $4,000
Impressions
680,000
Clicks
12,400
CTR
1.82%
CPC
$0.26
Conversions
342
CPA
$9.47
Retargeting — Warm Audiences
Facebook + Instagram · Last updated 5h ago
$2,890
/ $3,000
Impressions
510,000
Clicks
9,820
CTR
1.93%
CPC
$0.29
Conversions
318
CPA
$9.09
Competitor Keywords — High Intent
Search · Last updated 1d ago
$1,540
/ $2,500
Impressions
320,000
Clicks
6,100
CTR
1.91%
CPC
$0.25
Conversions
204
CPA
$7.55
Lookalike Expansion — Top 5%
Instagram · Last updated 3h ago
$2,180
/ $3,500
Impressions
390,000
Clicks
7,540
CTR
1.93%
CPC
$0.29
Conversions
218
CPA
$10.00
Display Network — Summer Launch
Display · Created today
$0
/ $5,000
Impressions
—
Clicks
—
CTR
—
CPC
—
Conversions
—
CPA
—
No campaigns match this filter.
Content Studio
Generate channel-specific ad copy from your offer brief
Describe the offer, its value proposition, key benefits, and target action.
Choose one or more channels to generate copy for.
Select the audience this copy should resonate with.
Female, 28–38 · SaaS · Series A–B stage
Male, 30–42 · Engineering · Mid-market
Female, 25–35 · B2B SaaS · Growth stage
Male, 35–50 · Operations · SMB / Enterprise
Generating Your Content
Retrieving similar offers from Qdrant…
0%
Headlines (max 30 chars each)
Responsive Search AdDescriptions (max 90 chars each)
Primary Text
Headlines (max 40 chars each)
Page Copy
Subject Line Variants
Email Body Preview
Broadcast Email
Request Revision
Describe what to change or improve.
Promote To
Qdrant Context
3 matchesSimilar offers retrieved from vector store.
"Free trial, no credit card. Cut sync meetings by 40%…"
"30-day trial, teams ship 2x faster, remote-first…"
"Reclaim 10 hrs/week, works with Slack, no setup…"
Active Pages
2
Total Views
56,720
Total Leads
3,499
Avg CVR
5.66%
Deploy New Landing Page
Provision a full Cloudflare-backed landing page stack in seconds.
Landing Pages
3 pagesConversion Funnel
Infrastructure
Conversion Funnel
Infrastructure
Conversion Funnel
Infrastructure
Active Mailboxes
22
Emails Sent
4,240
Avg Open Rate
31.2%
Avg Reply Rate
8.4%
Sequences
3 activeSaaS Cold Outreach — Q3
Contacts
3,400
Sent
2,840
Opened
854
Replied
142
Fintech Founder Touch
Contacts
1,200
Sent
980
Opened
323
Replied
61
Enterprise Re-engage
Contacts
600
Sent
420
Opened
109
Replied
18
Mailbox Pool
4 mailboxesoutreach@adplatform.io
45/day limit · 38 sent today
hello@growthplatform.io
40/day limit · 41 sent today
team@adplatform.io
20/day limit · 18 sent today
contact@adplatform.co
10/day limit · 9 sent today
Subscribers
12,400
+340 this month
Avg Open Rate
40.1%
Avg CTR
9.0%
Unsub Rate
0.19%
Broadcasts
3 broadcastsJune Product Update
Sent
12,400
Delivered
12,180
Opened
4,872
Clicked
1,096
Unsub
24
Q2 Benchmark Report
Sent
9,800
Delivered
9,604
Opened
3,362
Clicked
882
Unsub
18
July Roadmap Preview
Subscriber Segments
5 segments66.1% of total
22.6% of total
8.9% of total
2.4% of total
Total Spend MTD
$11,010
Jun 1 – Jun 13
Total Leads
3,499
All channels
Blended CPA
$3.15
Cost per lead
Best Channel
Meta Retarget
Lowest CPA $6.67
Weekly Spend — Google vs Meta
Channel Comparison
CPA — lower is better
Scale based on max CPA $10.00
Full Attribution Table
MTD performance across all channels
| Channel | Spend | Leads | CPA | Open Rate | CVR | ROAS |
|---|---|---|---|---|---|---|
| Google Ads | $3,800 | 380 | $10.00 | — | 4.2% | 2.8x |
| Meta Ads | $2,550 | 300 | $8.50 | — | 5.1% | 3.2x |
| Meta Retarget Best | $1,600 | 240 | $6.67 | — | 8.4% | 4.1x |
| Cold Email | $1,260 | 300 | $4.20 | 34.2% | 6.8% | 5.6x |
| Landing Pages | $930 | 300 | $3.10 | — | 11.2% | 7.2x |
| Organic / Direct | $870 | 1,979 | $0.44 | — | — | 18.4x |
| Total / Blended | $11,010 | 3,499 | $3.15 | — | 7.1% | 6.1x |
Tech Stack
Workflows
End-to-end operational playbooks across all AdOS systems
Launch Ad Campaign (Google)
Full-funnel workflow from offer brief through AI content generation, Google Ads API construction, and final campaign enablement. 15 steps across UX, AI Layer, Platform Layer, Storage, and Streaming.
- 1User UX
Submits offer brief + selects persona + targeting
- 2ContentGenerator AI Layer
Retrieves 5 similar offers from Qdrant, builds prompt
- 3Claude API AI Layer
Generates 15 headlines, 4 descriptions (RSA format)
- 4User UX
Reviews variants, approves, promotes to campaign
- 5GoogleAdapter Platform Layer
Creates CampaignBudget via Google Ads API v23
- 6GoogleAdapter Platform Layer
Creates Campaign (status=PAUSED, objective, bidding)
- 7GoogleAdapter Platform Layer
Sets CampaignCriteria (geo, device, language)
- 8GoogleAdapter Platform Layer
Creates AdGroup
- 9GoogleAdapter Platform Layer
Creates AdGroupCriteria (keywords, audience segments)
- 10GoogleAdapter Platform Layer
Uploads Assets (headlines, descriptions)
- 11GoogleAdapter Platform Layer
Creates ResponsiveSearchAd referencing assets
- 12Postgres Storage
Stores campaign state, platform_campaign_id, spec
- 13Redpanda Streaming
Publishes campaign_created event
- 14User UX
Reviews paused campaign → clicks Enable
- 15GoogleAdapter Platform Layer
Enables Campaign → AdGroup → Ad in sequence
Launch Ad Campaign (Meta)
Streamlined Meta Ads workflow from content approval through AdAccount validation, creative asset upload, and full campaign object hierarchy construction. 9 steps across UX, Platform Layer, Storage, and Cache.
- 1User UX
Approves Meta ad content from Content Studio
- 2MetaAdapter Platform Layer
Validates AdAccount + Page access
- 3MetaAdapter Platform Layer
Uploads AdImage → receives image hash
- 4MetaAdapter Platform Layer
Creates AdCampaign (objective, status=PAUSED)
- 5MetaAdapter Platform Layer
Creates AdSet (targeting_spec, budget, schedule, bid_strategy)
- 6MetaAdapter Platform Layer
Creates AdCreative (page_id + image_hash + copy)
- 7MetaAdapter Platform Layer
Creates Ad (references AdSet + AdCreative)
- 8Postgres Storage
Stores full campaign state + all platform IDs
- 9Dragonfly Cache
Caches campaign spec for fast retrieval
Content Generation Pipeline
AI-powered multi-channel content creation from offer brief through embedding-based retrieval, Claude generation, validation, and human review with revision loop. 10 steps across UX, AI Layer, and Storage.
- 1User UX
Enters offer description, picks persona
- 2ContentGenerator AI Layer
Embeds offer description via bge embedding model
- 3Qdrant AI Layer
Returns top-5 similar high-CTR offers as few-shot context
- 4ContentGenerator AI Layer
Builds per-channel prompt with persona + similar offers + format constraints
- 5Claude API AI Layer
Generates N variants: Google RSA, Meta, Landing Page, Cold Email, Broadcast
- 6ContentGenerator AI Layer
Validates character limits per platform, rejects overflows
- 7Postgres Storage
Stores ContentDraft with status=draft
- 8User UX
Reviews all channel outputs, requests revisions or approves
- 9ContentGenerator AI Layer
Revision: appends instruction to original prompt, regenerates
- 10User UX
Promotes approved content to Campaign / Landing Page / Sequence
Data Ingestion Pipeline
Scheduled multi-source metrics ingestion from Google and Meta platform APIs, through Redpanda streaming, Flink processing with Bronze/Silver/Gold Iceberg layers, and real-time Pinot OLAP serving. 11 steps.
- 1Scheduler API Layer
Triggers hourly pull for all active campaigns
- 2GoogleAdapter Platform Layer
GAQL query via SearchStream → raw CampaignMetrics
- 3MetaAdapter Platform Layer
Insights edge query → raw CampaignMetrics
- 4CFWorker Edge Layer
Lead form submit fires webhook → FastAPI
- 5Redpanda Producer Streaming
Publishes to: ads.google.metrics, ads.meta.metrics, ads.leads
- 6Flink Consumer Streaming
Normalizes cost_micros → USD, deduplicates by campaign_id+date
- 7Flink Consumer Streaming
Writes Bronze (raw) → Iceberg via WAP pattern
- 8Flink Consumer Streaming
Applies Silver transforms: joins, enrichment, schema enforcement
- 9SQLMesh Storage
Builds Gold tables: daily_campaign_summary, channel_comparison, content_performance
- 10Pinot OLAP
Ingests from Iceberg Silver tables for real-time OLAP queries
- 11Dashboard UX
Queries Pinot for sub-second cross-platform metrics
Landing Page Deploy
Automated landing page provisioning from approved copy through Cloudflare D1 database creation, DNS configuration, Worker script rendering, deployment, and campaign URL update. 9 steps across UX, API Layer, Edge Layer, Storage, and Platform Layer.
- 1User UX
Approves landing page copy from Content Studio
- 2LandingPageOrchestrator API Layer
Generates slug from campaign name
- 3Cloudflare API Edge Layer
Creates D1 database for lead storage
- 4Cloudflare API Edge Layer
Creates DNS CNAME record: {slug}.lp.domain.com → workers.dev
- 5LandingPageOrchestrator API Layer
Renders Worker script: HTML template + pixel config + form handler
- 6Cloudflare API Edge Layer
Deploys Worker with route binding to CNAME
- 7Cloudflare API Edge Layer
Wires Analytics Engine for page view tracking
- 8Postgres Storage
Stores LandingPage record with worker_name, d1_id, slug, status=live
- 9CampaignAdapter Platform Layer
Updates campaign destination_url to new page URL
Launch Readiness Timeline
Ad Platform Access
3–7 week lead time before first live campaign
Google requires a Developer Token to access the Google Ads API. Standard access is granted after review and requires demonstrating a working integration. Basic access has lower limits; you must apply for Standard access once ready to scale. The review process takes 2–4 weeks and is not guaranteed on the first submission.
- Create a Google Ads Manager (MCC) account
- Apply for Developer Token under API Center
- Build and document an integration for review
- Apply for Standard access once basic token is approved
- Store token securely in Cloudflare secrets
Meta's Marketing API requires app review to unlock advanced features like ad creation and management at scale. Unreviewed apps have significant rate limits and restricted capabilities. App review involves submitting a detailed use-case description and a screencast of the integration. Budget at least 2–4 weeks for approval and potential resubmission.
- Create a Meta Business Portfolio and verify the business
- Create a Meta App in the Developer Portal
- Submit for App Review with use-case documentation
- Generate long-lived system user access tokens
- Store credentials in Cloudflare secrets manager
Each managed client account requires valid billing and must comply with Google's advertising policies. New accounts may undergo automatic policy review before ads are approved to serve. B2B lead generation verticals sometimes trigger additional scrutiny. Prepare compliant landing pages and ad copy before going live.
- Set up billing profiles for each client sub-account
- Review Google Ads policies for each target vertical
- Ensure landing pages meet URL policy requirements
- Enable conversion tracking before first spend
Email Infrastructure
6–10 weeks from domain purchase to first cold send
Cold email at scale requires dedicated sending domains that are never used for primary business communication. Domain age matters for deliverability — providers use domain registration date as a trust signal. Each client campaign should use unique sending domains to isolate reputation. Plan to register domains well in advance of any campaign launch. Annual registration fees apply per domain and scale linearly with your domain portfolio.
- Register dedicated sending domains immediately (day 0)
- Use brand-adjacent variations, not the primary domain
- Plan for 2–3 sending domains per active campaign client
- Register through Cloudflare Registrar for unified management
New mailboxes must be warmed up gradually to build sender reputation with email providers. Sending too many emails too soon causes immediate deliverability problems and potential blacklisting. A proper warmup runs 6–8 weeks before any real outreach and requires automated warmup tooling. Tooling costs are subscription-based and priced by the number of active mailboxes. Each mailbox tops out at roughly 30–50 sends per day safely.
- Set up Google Workspace or Microsoft 365 for sending mailboxes
- Enroll all mailboxes in warmup tooling on day 14
- Do not send real outreach until warmup score is green (80+)
- Monitor deliverability scores throughout warmup
- Plan mailbox count based on target daily send volume
Every sending domain requires SPF, DKIM, and DMARC records configured correctly. Missing or misconfigured records cause immediate spam filtering or rejection. DMARC policy should be set to quarantine or reject with a reporting address. Cloudflare DNS management makes this repeatable via API or Terraform. Each domain also needs MX records pointed to its mail provider.
- Add SPF record allowing mail provider's servers
- Enable and publish DKIM keys for each mailbox provider
- Set DMARC policy to p=quarantine with rua reporting
- Verify configuration with MXToolbox or dmarcian
- Automate via Cloudflare API for domain portfolio at scale
Cold email volume is constrained by mailbox count and warmup status. Each warmed mailbox can safely send 30–50 emails per day. To reach 1,000 sends per day you need 20–35 active warmed mailboxes. Each mailbox needs its own domain or subdomain. Plan domain purchases and warmup starts around target go-live volume.
- Define target daily send volume per client
- Calculate required mailbox count (volume divided by 40)
- Register matching domain count on day 0
- Track warmup status per mailbox in system
DNS & Domain Management
Cloudflare manages all zones — plan domain portfolio upfront
All domains should be added to a single Cloudflare account and organized by purpose: landing page domains, sending domains, and the primary platform domain. Use Cloudflare Workers and Pages for landing page hosting. Zones can be managed programmatically via API, enabling automated provisioning as new client campaigns are onboarded. The Cloudflare free tier covers most DNS needs; paid plans unlock advanced features at usage-based pricing.
- Create Cloudflare account and add all domains as zones
- Define zone naming convention for client campaigns
- Enable API token scoped to DNS edit for automation
- Document zone IDs in configuration store
Ad platforms require landing page domains to match or be related to the advertiser's business domain. Using unrelated or suspicious domains triggers policy flags. Landing pages for cold email click tracking must use separate domains from email sending domains to avoid triggering spam filters when both are scanned together. Plan a clear domain naming convention before onboarding clients.
- Define landing page domain pattern per client
- Deploy landing pages on Cloudflare Pages
- Separate ad landing domains from email sending domains
- Enable HTTPS on all landing page domains
Campaign Management
Campaigns are not instant — plan for learning periods and A/B cycles
Google and Meta use machine learning to optimize ad delivery. New campaigns enter a "learning phase" of 1–2 weeks where performance is unstable. Significant budget, targeting, or creative changes reset the learning phase. The system should surface learning phase status and prevent users from making disruptive edits during this window without warnings.
- Expose learning phase status from both platform APIs
- Add UI warnings when editing a learning-phase campaign
- Advise clients to hold edits for at least 7 days after launch
Both Google and Meta have native A/B (Experiment) features that split traffic in a statistically controlled way. Using native experiments is preferred over manual split-testing because it avoids auction interference. Tests need enough volume to reach significance — low-budget campaigns may take 3–4 weeks to produce meaningful results. The system should manage experiment state and flag when tests reach significance.
- Integrate Google Ads Campaign Experiment API
- Integrate Meta A/B Test creation via Marketing API
- Build statistical significance tracker in dashboard
- Alert when test reaches 95% confidence
Platforms can overspend daily budgets by up to 100% on high-demand days, reconciling over the monthly billing period. This can cause cash flow issues if clients are billed on exact daily spend. The system should track cumulative spend against monthly targets and surface pacing alerts before overspend occurs. Budget changes mid-month can affect pacing calculations.
- Pull daily spend data from both platform APIs
- Build pacing calculator against monthly budget
- Alert when projected monthly spend exceeds target by 10%
Ad creatives lose effectiveness as audiences repeatedly see the same content. Meta surfaces a "creative fatigue" signal in the API. Google's frequency data requires manual calculation. The system should track frequency, CTR trends, and fatigue signals to prompt creative rotation before performance drops significantly.
- Pull Meta creative fatigue signal via Insights API
- Calculate frequency and CTR trends for Google ads
- Surface fatigue alerts in campaign dashboard
- Recommend creative rotation cadence per vertical
Multi-User & Permissions
Under 30 users: simple. Over 100: needs RBAC, audit logs, locking
The permission model complexity should scale with user count. At 1–30 users, a simple role system (Admin, Manager, Viewer) is sufficient. At 30–100 users, per-client access scoping becomes necessary. Over 100 users requires full RBAC with custom roles, audit logging, and granular resource permissions. Design the data model to support all tiers from the start, even if only simple roles are exposed initially.
- Implement base roles: Admin, Manager, Viewer
- Design schema for per-client access scoping
- Plan RBAC upgrade path in data model
- Add audit log table from day 1
Two users editing the same campaign simultaneously can cause race conditions that result in lost changes or conflicting platform state. Optimistic locking with last-write-wins is acceptable at small scale, but can cause silent data loss. For teams over 10 users, pessimistic locking (claim-to-edit) or operational transform should be implemented. At minimum, show who is currently editing a campaign.
- Add optimistic locking with version field to campaign records
- Show active editor presence indicator
- Warn on concurrent edit conflict
- Design claim-to-edit flow for future upgrade
Agency clients often need to approve copy and creative before campaigns go live. Without a built-in approval flow, teams use ad hoc email threads and spreadsheets, creating compliance risk and miscommunication. A lightweight review state (Draft, In Review, Approved, Published) covers most agency use cases without over-engineering.
- Add status state machine to campaign and sequence records
- Allow Manager role to request review
- Allow Admin or Client to approve or reject with comment
- Notify approver via email on review request
Data Pipeline & Latency
Platform data lags 3h. Iceberg query latency is minutes, not seconds.
Google Ads and Meta Ads reporting data is delayed by 2–3 hours and subject to late attribution revisions for up to 28 days (Meta) or 90 days (Google conversions). Users must understand they are not seeing real-time performance. The system should display data freshness timestamps and set appropriate expectations in the UI. Always-on polling is not effective — schedule syncs at sensible intervals.
- Display "Last synced" timestamp on all reporting views
- Schedule syncs at 3h intervals via Cloudflare Cron Triggers
- Re-pull last 30 days of Meta data nightly for attribution revisions
- Document latency expectations in client-facing documentation
Apache Iceberg on object storage (R2) is optimized for analytical batch queries, not interactive sub-second responses. Cold queries on large tables can take 30 seconds to several minutes depending on file count and partition pruning efficiency. The dashboard must use pre-aggregated summary tables or materialized views for any data shown on page load. Raw Iceberg tables should be used only for export or deep analysis.
- Create pre-aggregated summary tables updated on each sync
- Never query raw Iceberg tables in dashboard render path
- Cache summary results in Cloudflare KV or D1
- Expose async export for ad-hoc Iceberg queries
Reply ingestion is not handled by most cold email sending tools by default. Out-of-office replies, unsubscribe requests, and interested leads all arrive in the sending mailbox and require automated parsing to route correctly. Unsubscribes must be processed within 10 days under CAN-SPAM and 2 days under CASL. Implement polling or webhook-based reply ingestion from the sending mailbox provider.
- Implement IMAP polling or Google/Microsoft webhook for replies
- Auto-classify: OOO, unsubscribe, positive, negative
- Immediately suppress contact on unsubscribe keyword
- Route positive replies to CRM or notification queue
Legal & Compliance
CAN-SPAM, GDPR, CASL vary by target geography — non-negotiable
US (CAN-SPAM): B2B cold email is permissible with a physical address, clear sender identification, and working unsubscribe. Canada (CASL): requires express or implied consent — much stricter than CAN-SPAM. EU/UK (GDPR/PECR): requires legitimate interest basis and individual unsubscribe rights for every recipient. Australia (Spam Act): similar consent requirements to CASL. Each client's target geography must be confirmed before campaign launch to apply the correct compliance rules.
- Collect target geography at campaign creation
- Enforce physical address footer for all US campaigns
- Block Canada/EU campaigns without legal acknowledgment
- Build unsubscribe list as global suppression across all campaigns
- Consult legal counsel before EU/Canada campaign launch
Google and Meta have detailed advertising policies covering prohibited content, restricted categories, and destination requirements. Financial services, healthcare, and employment verticals require additional certifications on both platforms. Violations result in ad disapprovals, account suspensions, and in severe cases, permanent bans. Each client vertical should be screened before API credentials are used to create campaigns.
- Review Google Ads policy for each planned vertical
- Review Meta advertising standards for each vertical
- Apply for required certifications (financial services, healthcare)
- Add vertical flag to client onboarding flow
Contact lists and audience data uploaded to ad platforms (Custom Audiences) are subject to Meta's and Google's data use policies, which require confirming the data was collected with appropriate consent. Storing raw PII in the system also creates GDPR/CCPA obligations. Email addresses should be hashed before platform upload. The system should not retain contact data longer than needed for the active campaign.
- Hash email/phone before uploading to Meta Custom Audiences
- Accept terms of Meta's Custom Audience ToS per ad account
- Define data retention policy and implement automated purge
- Draft privacy policy and DPA templates for clients
Cost Model & Budgeting
Infrastructure, tooling, and domain costs scale with usage
Cloudflare Workers, R2, D1, KV, and Queues are all usage-based services. At low volume the costs are minimal; as client count and data volume grow, costs scale proportionally. The largest variable costs are R2 storage for Iceberg data (priced per GB stored and per operation) and Workers invocations for data pipeline jobs. Monitor usage via Cloudflare Analytics and set billing alerts. Infrastructure costs should be factored into client pricing to ensure margin.
- Enable Cloudflare billing alerts at defined usage thresholds
- Instrument per-client R2 and Worker usage attribution
- Model expected infrastructure costs at target client count
- Review Cloudflare Workers Paid plan limits vs projected usage
Key third-party tools include mailbox warmup tooling (subscription-based, priced by active mailbox volume), cold email sequencing software (subscription-based, priced by volume or seats), data enrichment APIs (priced per lookup or per record), and optional AI/LLM services for copy generation (priced per token or per generation). All are variable costs that grow with client campaigns. Evaluate open-source alternatives and batch API calls to manage costs at scale.
- List all third-party SaaS dependencies and their pricing models
- Model tooling cost per active client seat
- Identify which tools can be consolidated or replaced
- Set usage caps on enrichment API calls per campaign
Domain registrations are a recurring annual cost that scales directly with campaign count. Each client campaign may require several dedicated sending domains and at least one landing page domain. Annual registration fees apply per domain and should be tracked as a per-client overhead. Consolidate registrations under Cloudflare Registrar to benefit from at-cost pricing and centralized DNS management. Budget renewal costs annually.
- Estimate domain count at launch and at scale
- Use Cloudflare Registrar for at-cost renewal pricing
- Track domain renewal dates per client in system
- Enable auto-renew on all sending domains