Multi-Touch Revenue Attribution for Web Roguelikes: A Practical Guide
A practical guide to measuring true contribution of each monetization touchpoint and designing experiments without disrupting live operations in web roguelike games.
---
1. Why Single-Touch Attribution Fails in Roguelikes
Most small-scale roguelike developers treat conversions as single events. "User pressed the button, purchase happened" -- but this simple attribution misses the cumulative effect of dozens of touchpoints.
Purchase patterns in roguelikes are not single-session events but probabilistic accumulation across multiple sessions.
Typical conversion journey (web roguelike - avg 4.2 sessions to purchase):
--------------------------------------------------------------------------------
Session 1: Organic acquisition -> Tutorial -> 2-3 runs -> No ad exposure
Session 2: Watched rewarded ad -> 1 run -> Received 10 premium currency
Session 3: Clicked push notification -> Joined event -> Earned item (free)
Session 4: Received email -> Returned -> Watched ads x2 -> [CONVERSION] $4.99 skin purchase
Where was the conversion actually decided?
- Last-Touch says: Email (Session 4)
- First-Touch says: Organic (Session 1)
- Reality: Rewarded ad + Push + Email all contributed
---
2. Attribution Model Spectrum
Last-Touch (Default)
- Pros: Easy to implement, immediately available
- Cons: Distorts contribution in multi-session journeys
- Recommended for: Indie devs, early analytics phase
Position-Based (U-Shape) 40/20/20/20
- Pros: Recognizes both First-Touch and Last-Touch
- Cons: Underweights mid-funnel touchpoints
- Recommended for: Event-driven games
Time Decay
- Pros: Gives more weight to touchpoints closer to conversion
- Cons: Requires tuning of half-life parameter
- Recommended for: Roguelikes with long inter-session gaps
Markov Chain (Multi-Touch)
- Pros: State transition probabilities, Removal Effect available
- Cons: Requires validation of Markov chain stationarity
- Recommended for: Mid-size studios and above
---
3. Practical Implementation: Uplift Testing (Indie Recommended)
# uplift_test.py - Minimum Viable Uplift Framework
import pandas as pd
import numpy as np
from scipy import stats
class RoguelikeUpliftTest:
def __init__(self, exposed_rate=0.3):
self.exposed_rate = exposed_rate # Treatment group ratio
def assign_group(self, user_id: str, bucket: str = 'default') -> str:
"""Deterministic hashing for consistent assignment"""
import hashlib
h = hashlib.sha256(f"{user_id}-{bucket}".encode()).hexdigest()
bucket_value = int(h[:8], 16) % 10000 / 10000
if bucket_value < self.exposed_rate:
return 'treatment'
return 'control'
def calculate_uplift(self, df: pd.DataFrame) -> dict:
"""Calculate treatment effect with confidence interval"""
control = df[df.group == 'control'].converted
treatment = df[df.group == 'treatment'].converted
# T-test
t_stat, p_val = stats.ttest_ind(treatment, control)
effect_size = treatment.mean() - control.mean()
relative_uplift = effect_size / control.mean() * 100
return {
'control_conversion_rate': control.mean(),
'treatment_conversion_rate': treatment.mean(),
'absolute_uplift': effect_size,
'relative_uplift_pct': relative_uplift,
'p_value': p_val,
'statistically_significant': p_val < 0.05,
'required_sample_per_group': self._min_sample_size(
baseline_rate=control.mean(),
mde=0.01 # Minimum Detectable Effect: 1%
)
}
def _min_sample_size(self, baseline_rate: float, mde: float,
alpha: float = 0.05, power: float = 0.80) -> int:
"""Two-proportion z-test sample size calculation"""
from statsmodels.stats.power import NormalIndPower
analysis = NormalIndPower()
effect_size = mde / (baseline_rate * (1 - baseline_rate)) ** 0.5
sample = analysis.solve_power(
effect_size=effect_size,
alpha=alpha,
power=power,
alternative='two-sided'
)
return int(np.ceil(sample))
---
4. Policy and Privacy Compliance
AdSense & AdMob Policy
- No personally identifiable information for conversion tracking
- Cookie-based tracking requires GDPR/CCPA compliance
GDPR & Privacy (EEA Users)
- Implement Consent Management Platform (IAB TCF v2.2)
- Document legal basis for data processing
- Establish user data deletion request workflow
Child Protection (Global)
- Korea PIPA: Parental consent required for children under 14
- EU COPPA-equivalent: GDPR Article 8
---
5. Implementation Roadmap
| Phase | Scope | Time Required | Cost |
|---|---|---|---|
| 1 | GA4/Firebase + basic event logging | 1-2 weeks | $0 (free tiers) |
| 2 | U-Shape + Time Decay comparison | 1 month | $50-$300/month |
| 3 | Markov Chain Attribution | 2-3 months | $2,000+/month |
---