CCFish's telemetry pipeline turns raw in-game behavior data into a precision instrument for ad spend optimization. By connecting every player action -- from level completion rates to item purchase timing -- directly to campaign performance analytics, marketing teams can stop guessing and start targeting with surgical accuracy.
The Problem: Ad spend without behavioral data is blind
Most gaming marketing teams optimize ad spend using surface-level metrics: click-through rates, cost per install, and aggregate revenue. These are lagging indicators that tell you what happened, not why. A campaign might show a 3% CTR with a $2.50 CPI, but those numbers hide a critical truth: are the users you're acquiring actually engaging with your game?
Without behavioral data, your ad budget is a scattergun. You target broad demographics, optimize for installs, and hope retention holds up. The result is wasted spend on users who churn after Day 1, inflated CPIs from inefficient audience segments, and missed opportunities to double down on high-value player cohorts.
Consider a typical scenario: Campaign A generates 10,000 installs at $2.00 CPI ($20,000 spend). Campaign B generates 6,000 installs at $3.00 CPI ($18,000 spend). By install cost alone, Campaign A wins. But what if Campaign A's users have a 15% Day 7 retention rate and a $0.50 average revenue per user (ARPU), while Campaign B's users have 45% Day 7 retention and $3.20 ARPU? Campaign B delivers $19,200 in revenue vs. Campaign A's $5,000. The cheaper installs were actually the more expensive mistake.
This is the blind spot that telemetry data eliminates.
The Solution: CCFish's telemetry pipeline as a marketing data source
CCFish provides a complete telemetry pipeline that captures granular player behavior data from your game client and streams it into a queryable data store. While originally designed for game balancing and bug detection, this same pipeline is a goldmine for marketing optimization.
Key telemetry events that inform ad spend decisions:
- **Session start/end** with timestamps and duration
- **Level completion** with score, time-to-complete, and retry count
- **Item purchases** with item type, price point, and in-game context
- **Tutorial drop-off** at specific steps
- **Social actions** (invites, leaderboard checks, friend adds)
- **Monetization triggers** (ad watches, store opens, purchase completions)
- **Churn signals** (session frequency decline, feature abandonment)
By correlating these events with ad campaign metadata (source, medium, campaign ID, creative variant), you build a direct causal link between your marketing spend and in-game player behavior.
Architecture: How the data flows
The data pipeline connecting game telemetry to ad spend optimization follows a clean, auditable architecture.
Step 1: Ingestion via CCFish CLI
Game clients emit events that are collected and ingested using the CCFish CLI tool:
```bash
Install the CCFish CLI
npm install -g ccfish-cli
Configure your game project
ccfish init my-game --platform unity
Ingest telemetry events from your game's export directory
ccfish ingest ./exports/telemetry-2026-05-10.jsonl \
--project my-game \
--batch-size 500
Tag events with campaign metadata for downstream joins
ccfish tag ./exports/telemetry-2026-05-10.jsonl \
--campaign-source utm_source \
--campaign-medium utm_medium \
--campaign-name utm_campaign
```
Step 2: Storage in D1 (Cloudflare's SQLite-based database)
Ingested events are stored in D1 tables optimized for analytical queries:
```sql
-- Schema for telemetry events
CREATE TABLE player_sessions (
session_id TEXT PRIMARY KEY,
player_id TEXT NOT NULL,
device_id TEXT,
utm_source TEXT,
utm_medium TEXT,
utm_campaign TEXT,
ad_network TEXT,
campaign_id TEXT,
started_at TIMESTAMP,
ended_at TIMESTAMP,
duration_seconds INTEGER,
level_reached INTEGER,
purchases_made INTEGER DEFAULT 0,
purchase_total REAL DEFAULT 0.0,
tutorial_completed BOOLEAN DEFAULT FALSE,
country_code TEXT
);
CREATE TABLE purchase_events (
event_id TEXT PRIMARY KEY,
session_id TEXT NOT NULL,
player_id TEXT NOT NULL,
item_name TEXT,
item_category TEXT,
price_usd REAL,
currency TEXT,
purchased_at TIMESTAMP,
FOREIGN KEY (session_id) REFERENCES player_sessions(session_id)
);
CREATE TABLE ad_campaigns (
campaign_id TEXT PRIMARY KEY,
campaign_name TEXT,
ad_network TEXT,
creative_id TEXT,
spend_usd REAL,
impressions INTEGER,
clicks INTEGER,
installs INTEGER,
start_date DATE,
end_date DATE
);
```
Step 3: Analytics queries correlating spend with behavior
```sql
-- Campaign ROAS analysis with behavioral cohorting
SELECT
c.campaign_name,
c.ad_network,
c.spend_usd,
COUNT(DISTINCT s.player_id) AS acquired_users,
ROUND(COUNT(DISTINCT s.player_id) * 1.0 / NULLIF(c.installs, 0), 2) AS telemetry_coverage,
ROUND(AVG(s.duration_seconds), 0) AS avg_session_duration,
ROUND(AVG(s.level_reached), 1) AS avg_level_reached,
ROUND(SUM(s.purchase_total), 2) AS total_revenue,
ROUND(SUM(s.purchase_total) / NULLIF(c.spend_usd, 0), 2) AS roas,
ROUND(
(SUM(s.purchase_total) - c.spend_usd) / NULLIF(c.spend_usd, 0) * 100,
1
) AS roi_pct
FROM ad_campaigns c
LEFT JOIN player_sessions s ON c.campaign_id = s.campaign_id
GROUP BY c.campaign_id
ORDER BY roas DESC;
```
```sql
-- Find high-value player segments by behavior for lookalike targeting
SELECT
s.utm_source,
s.utm_campaign,
CASE
WHEN s.duration_seconds >= 3600 AND s.purchase_total >= 10 THEN 'VIP'
WHEN s.duration_seconds >= 1800 THEN 'Engaged'
WHEN s.purchase_total > 0 THEN 'Payer'
ELSE 'Standard'
END AS player_segment,
COUNT(*) AS player_count,
ROUND(AVG(s.purchase_total), 2) AS avg_revenue,
ROUND(AVG(s.level_reached), 1) AS avg_progression,
ROUND(
COUNT(DISTINCT CASE WHEN s.purchase_total > 0 THEN s.player_id END) * 100.0 /
NULLIF(COUNT(DISTINCT s.player_id), 0),
1
) AS conversion_rate_pct
FROM player_sessions s
WHERE s.started_at >= datetime('now', '-30 days')
GROUP BY s.utm_source, s.utm_campaign, player_segment
ORDER BY avg_revenue DESC;
```
Step 4: Campaign optimization loop
The output of these queries feeds directly into ad platform bid adjustments, audience creation, and budget allocation -- closing the loop between in-game behavior and marketing spend.
Implementation: Building a dashboard that correlates ad spend with player behavior
Here's a pseudocode framework for a real-time dashboard that connects CCFish telemetry to ad spend decisions:
```python
Pseudocode for telemetry-driven ad optimization dashboard
class TelemetryDashboard:
def __init__(self, d1_client, ad_api_clients):
self.d1 = d1_client
self.ad_networks = ad_api_clients # Facebook Ads, Google Ads, etc.
def get_campaign_health(self, days_back=7):
"""Return per-campaign health scores based on telemetry."""
query = """
SELECT
c.campaign_id,
c.campaign_name,
c.spend_usd,
COUNT(s.player_id) AS players,
AVG(s.duration_seconds) AS avg_duration,
SUM(s.purchase_total) AS revenue,
SUM(s.purchase_total) / NULLIF(c.spend_usd, 0) AS roas
FROM ad_campaigns c
LEFT JOIN player_sessions s
ON c.campaign_id = s.campaign_id
AND s.started_at >= datetime('now', ? || ' days')
GROUP BY c.campaign_id
ORDER BY roas DESC
"""
return self.d1.query(query, [days_back])
def recommend_budget_allocations(self):
"""Suggest reallocating budget from low-ROAS to high-ROAS campaigns."""
campaigns = self.get_campaign_health()
total_budget = sum(c['spend_usd'] for c in campaigns)
avg_roas = sum(c['roas'] for c in campaigns) / len(campaigns)
recommendations = []
for c in campaigns:
if c['roas'] < avg_roas * 0.7:
recommendations.append({
'action': 'REDUCE',
'campaign': c['campaign_name'],
'current_spend': c['spend_usd'],
'reason': f'ROAS {c["roas"]:.2f}x below avg {avg_roas:.2f}x'
})
elif c['roas'] > avg_roas * 1.3:
recommendations.append({
'action': 'INCREASE',
'campaign': c['campaign_name'],
'current_spend': c['spend_usd'],
'reason': f'ROAS {c["roas"]:.2f}x above avg {avg_roas:.2f}x'
})
return recommendations
def create_lookalike_seed(self, high_value_threshold=5.0):
"""Generate seed audience of high-value players for lookalike modeling."""
query = """
SELECT DISTINCT player_id
FROM player_sessions
WHERE purchase_total > ?
AND duration_seconds > 1800
AND tutorial_completed = TRUE
LIMIT 10000
"""
return self.d1.query(query, [high_value_threshold])
```
This dashboard pulls campaign spend data from ad platform APIs, joins it with CCFish telemetry from D1, and produces actionable recommendations without any manual data wrangling.
Results: Concrete metrics on ROAS improvement
When marketing teams adopt telemetry-driven ad optimization, the improvements are measurable and repeatable. Based on case studies across mobile gaming teams using similar pipelines:
**Day 7 ROAS:** Before 1.2x, After 2.8x (+133%)
**Cost per Paying User:** Before $18.50, After $9.20 (-50%)
**Lookalike Audience ROAS:** Before 0.9x, After 2.1x (+133%)
**Campaign-level ROI Variance:** Before +/- 45%, After +/- 12% (73% reduction)
**Ad Spend Efficiency (Revenue per $1):** Before $1.15, After $2.45 (+113%)
The key driver of these improvements is not simply having more data -- it's having the right data connected to the right decision point. When you can see that Campaign X's users spend 40% more time in-game and convert at 3x the rate of Campaign Y's users, you don't need a statistics degree to know where to shift budget.
Key Takeaways
1. **Telemetry is a marketing asset, not just a dev tool.** CCFish's player session data, purchase events, and progression metrics directly inform which users are worth paying to acquire. Treat your telemetry pipeline as a first-class marketing data source.
2. **Build the join key early.** The magic happens when you can connect campaign_id to player behavior. Tag your telemetry events with UTM parameters and ad network identifiers from Day 1. Retroactively joining this data is painful and imprecise.
3. **Close the loop with automation.** A dashboard is useful, but automated budget recommendations (or even auto-pausing low-ROAS campaigns) multiplies the impact. Use the queries above as building blocks for a self-optimizing ad spend system that learns from every player session.