CCFish uses automated event triggers, scheduled messaging, and player segmentation to run marketing campaigns without manual intervention — turning every in-game action into a personalized engagement opportunity at scale.
The Problem
Mobile games with millions of daily active players face a fundamental marketing challenge: manual campaign management doesn't scale. A typical mid-size game studio runs dozens of simultaneous campaigns — welcome sequences, reactivation nudges, purchase prompts, level-up congratulations, referral incentives, and seasonal events. Each campaign requires a marketer to define the audience, write the copy, schedule the send time, pick the channel, and measure the result. When your player base spans multiple time zones, languages, and behavioral cohorts, a human team simply cannot personalize every touchpoint for every player.
Worse, manual campaigns suffer from latency. A player who completes a difficult level or makes their first purchase is most receptive to engagement in the minutes that follow, not the next day when a marketer manually triggers a sequence. By the time a human schedules the campaign, the emotional window has closed, and the player has moved on.
Manual campaigns also introduce inconsistency. Different team members write different tones, apply different segmentation logic, and use different timing strategies. Players notice the disjointed experience, and engagement metrics suffer as a result.
The Solution
CCFish's event-driven marketing pipeline solves these problems by connecting in-game events directly to automated marketing actions. The core principle is simple: **every player action generates an event, every event can trigger a campaign, and every campaign is personalized by player segment.**
The pipeline operates in four stages:
1. **Event Capture** — Game client or server emits a structured event when a player performs an action (login, purchase, level-up, referral, session end, etc.)
2. **Rule Evaluation** — A rules engine matches the event against configured campaign rules. Each rule specifies a condition (e.g., "event.type == purchase AND event.first_purchase == true") and a campaign action
3. **Message Assembly** — The system builds a personalized message using player attributes (name, level, currency balance, referral count) and campaign templates
4. **Delivery** — The message is sent via the optimal channel (push notification, in-app message, email, or SMS) based on player channel preferences and campaign configuration
All of this happens in real time — from event to delivered message in under 200 milliseconds.
Architecture Overview
CCFish's automated marketing system is built on four core components:
```
┌─────────────┐ ┌──────────────┐ ┌────────────┐ ┌──────────────────┐
│ Event Bus │───→│ Rule Engine │───→│ Scheduler │───→│ Delivery Channels │
│ (Kafka) │ │ (Drools) │ │ (Redis) │ │ (APNS/FCM/SES) │
└─────────────┘ └──────────────┘ └────────────┘ └──────────────────┘
│ │ │
↓ ↓ ↓
┌─────────────┐ ┌──────────────┐ ┌──────────────────┐
│ Event Log │ │ Player │ │ Metrics │
│ (S3/Parquet)│ │ Segmentation │ │ Dashboard │
└─────────────┘ │ Service │ │ (Prometheus) │
└──────────────┘ └──────────────────┘
```
Event Bus
All game events are published to a Kafka cluster. This decouples event producers (game servers) from event consumers (the marketing system). Events are schema-validated using Avro to ensure every marketing campaign receives properly structured data. The event schema includes:
```json
{
"event_id": "uuid",
"event_type": "purchase.completed",
"player_id": "uuid",
"timestamp": 1717603200000,
"properties": {
"item_id": "gem_pack_5",
"price_usd": 4.99,
"first_purchase": true
}
}
```
Rule Engine
Campaign rules are defined in a lightweight DSL and evaluated by a Drools rules engine. Each rule specifies:
- **Trigger event**: The event type that activates the rule
- **Conditions**: Boolean expressions over event properties and player attributes
- **Cooldown**: Minimum time between repeated triggers for the same player (prevents spam)
- **Segmentation**: Target player segments the rule applies to
- **Campaign reference**: The campaign template to deploy
Example rule:
```
rule "First Purchase Welcome"
when
$event : GameEvent(eventType == "purchase.completed",
properties.firstPurchase == true)
$player : PlayerSegment(segment in {"new", "trial_converted"})
then
enqueueCampaign("welcome_first_purchase", $player);
end
```
Scheduler
Not all campaigns should trigger instantly. The scheduler, backed by Redis sorted sets, handles delayed and recurring campaigns:
- **Immediate**: Push notification sent within 200ms of the event
- **Delayed**: Scheduled message sent after a configurable delay (e.g., "3 days after first login")
- **Recurring**: Repeating campaigns (e.g., "send a weekly digest every Monday at 10 AM local time")
- **Batched**: Aggregated notifications sent daily (e.g., "you have 3 unread friend requests")
Delivery Channels
The system supports four delivery channels with automatic fallback:
1. **Push notifications** (APNS for iOS, FCM for Android) — highest engagement
2. **In-app messages** — displayed within the game UI
3. **Email** (AWS SES) — preferred for rich content and receipts
4. **SMS** (Twilio) — used only for critical account events (password reset, 2FA)
Each player has a channel preference stored in the profile service. The system respects opt-out preferences at both the channel level and the campaign category level.
Implementation
Here's how specific game events trigger automated campaigns in CCFish:
Login Events
When a player logs in after 7+ days of inactivity, the system fires a "reactivation" campaign:
```python
async def handle_login_event(event: GameEvent):
player = await player_service.get_player(event.player_id)
days_since_last_login = (
datetime.utcnow() - player.last_login
).days
if days_since_last_login >= 7:
campaign = "reactivation_day_7"
message = build_reactivation_message(player, days_since_last_login)
await campaign_service.enqueue(campaign, player.id, message)
if days_since_last_login >= 30:
Offer a compelling return incentive
campaign = "reactivation_day_30"
message = build_return_incentive(player)
await campaign_service.enqueue(campaign, player.id, message)
```
Purchase Events
Purchase events power the most revenue-critical campaigns. Upon a first purchase, the system sends a thank-you message and upsells to a subscription tier. For high-value spenders (whales), the system escalates to a priority queue:
```python
async def handle_purchase_event(event: GameEvent):
player = await player_service.get_player(event.player_id)
purchase = Purchase(**event.properties)
if purchase.first_purchase:
await campaign_service.enqueue(
"first_purchase_thank_you",
player.id,
{"title": "Thanks, Captain!",
"body": "Your support means the world. Here's 50 bonus gems!"}
)
elif purchase.total_usd >= 20:
await campaign_service.enqueue(
"whale_upsell",
player.id,
build_whale_upsell(player, purchase)
)
```
Level-Up Events
Level-ups create natural engagement moments. The system congratulates the player, hints at upcoming content, and (strategically) offers a discounted bundle tied to the new level bracket:
```python
async def handle_level_up_event(event: GameEvent):
new_level = event.properties.get("new_level", 0)
player = await player_service.get_player(event.player_id)
Every milestone level triggers a campaign
if new_level in LEVEL_MILESTONES:
await campaign_service.enqueue(
"level_milestone",
player.id,
build_level_up_message(player, new_level)
)
Level-appropriate store bundle offer
bundle = bundle_service.get_bundle_for_level(new_level)
if bundle:
await campaign_service.enqueue(
"level_bundle_offer",
player.id,
build_bundle_offer(player, bundle),
delay_minutes=30 # Give them time to enjoy the level first
)
```
Referral Events
Referrals are tracked end-to-end. When a referred player completes their first session, the referrer receives a reward notification. When the referral makes their first purchase, both parties get a bonus. This creates a viral loop without manual intervention:
```python
async def handle_referral_event(event: GameEvent):
referrer_id = event.properties.get("referrer_id")
if not referrer_id:
return
referral = ReferralEvent(**event.properties)
if referral.event_type == "referral.signup":
await campaign_service.enqueue(
"referral_reward_signup",
referrer_id,
build_referral_reward_message(referral)
)
elif referral.event_type == "referral.purchase":
await campaign_service.enqueue(
"referral_reward_purchase",
referrer_id,
build_purchase_reward(referral)
)
await campaign_service.enqueue(
"referral_welcome_purchase",
referral.new_player_id,
build_first_purchase_referral_message()
)
```
Results
After deploying the automated event marketing system, CCFish measured the following improvements over the previous manual campaign process:
| Metric | Before (Manual) | After (Automated) | Improvement |
|---|---|---|---|
| Campaign delivery latency | 6-24 hours | < 200ms | 99.9% reduction |
| Player reactivation rate | 4.2% | 11.8% | +180% |
| First-purchase conversion | 2.1% | 4.7% | +124% |
| Weekly active user retention | 38% | 51% | +34% |
| Marketing team hours/week | 120+ | 12 | -90% |
| Campaigns running concurrently | 8-12 | 45+ | 4x increase |
Most notably, the marketing team was able to reduce campaign management overhead from over 120 person-hours per week to just 12 — mostly spent on monitoring and A/B testing new rule templates. The system now runs 45+ concurrent campaigns covering every major player lifecycle stage, with no manual intervention.
Key Takeaways
1. **Event-driven marketing eliminates latency**: By connecting in-game events directly to campaign triggers, you reach players when their engagement is highest — within moments of the action, not hours later.
2. **Segmentation amplifies relevance**: Raw events + player profile data = highly personalized messages. A new free player and a veteran whale get different treatments from the same event trigger.
3. **Rules over scripts**: A declarative rules engine makes it possible for non-engineers (marketers, product managers) to define campaign logic without writing code. Changes go from concept to production in minutes.
4. **Cooldowns prevent spam**: Every rule includes cooldown logic. Players never receive two campaign messages within a configurable window, preserving the channel's effectiveness.
5. **Start with four event types**: Login, purchase, level-up, and referral cover 80%+ of valuable marketing moments. Add more (session-end, friend-invite, achievement-unlock) as the system matures.
6. **Measure everything**: Every campaign event is logged to a metrics pipeline. Conversion rates, message open rates, and reactivation lift are visible on a real-time dashboard. If you can't measure it, you can't optimize it.
Automated event marketing is not about replacing marketers — it's about freeing them from repetitive campaign management so they can focus on strategy, creative, and optimization. CCFish's system proves that with the right architecture, a mobile game can deliver personalized, timely, and effective marketing to millions of players without a massive operations team.