Your casino generated €2.4M in revenue last month. Your affiliate system says you owe €840K in commissions. Your finance team pulls the gaming platform’s revenue report and sees €2.1M. Your payment processor shows €2.6M in deposits.
Which number is correct?
All of them. And none of them.

This is the reconciliation nightmare that costs casino operators real money—not because the systems are “broken,” but because nobody built a coherent framework for how affiliate data, platform data, PSP data, and CRM data should align.
Operators who treat BI integration as an afterthought end up burning dozens of hours a month reconciling spreadsheets, disputing affiliate payouts, and making acquisition decisions based on incomplete (or mismatched) numbers.
The operators who get this right build automated pipelines that flow from raw click events to executive dashboards showing: which affiliates drive profitable players, which traffic sources have the best LTV, and where commission budget should actually be allocated.
This guide shows you how to structure affiliate data exports, integrate with your BI stack, and build reconciliation frameworks that work in production—without needing a data science PhD.
What you’ll be able to answer (fast) when this is implemented?
Before we go technical, here’s the real “why” (the questions your CFO and Head of Acquisition will ask):
- Which affiliates are profitable after bonuses, fees, chargebacks, and commission?
- Which SubID clusters (placements/creatives) generate retained players instead of one-and-done FTDs?
- Which GEOs look “great” on deposits but are negative after withdrawals + bonus cost?
- Which commission plans are mathematically broken (commission rate drifts vs actual NGR)?
- Which affiliates are repeatedly triggering disputes because your evidence chain is incomplete?
Why casino BI integration is harder than e-commerce?
In e-commerce, the flow is usually: click → purchase → revenue. One event, one transaction, done.
Casino attribution is fundamentally more complex:
Multiple revenue-impacting events per player
A single player generates registration, KYC approval, deposits, wagering activity, bonus claims, withdrawals, chargebacks, and ongoing NGR over time. Each event affects commission and profitability differently.
Time lag between attribution and revenue
A player clicks an affiliate link on January 5, registers on January 7, makes first deposit on January 10, and generates €500 NGR over the next 90 days. Which month does that NGR “belong” to? When do you pay? What happens if the deposit is charged back on February 3?
CPA is simple: one payable moment. RevShare means you’re calculating commission on player activity every month for potentially years. Your BI needs to track player lifetime value by affiliate source indefinitely.
You’re reconciling multiple systems, not one “truth”
Your affiliate system tracks clicks and attribution. Your gaming platform tracks wagers and NGR. Your PSP tracks deposits and withdrawals. Your CRM tracks segmentation and player lifecycle status. All four must agree on which players belong to which affiliate attribution—and how revenue is defined.
If your warehouse can’t join these sources reliably, your profitability analysis is fiction.
The core data architecture that actually works
Before export formats and schemas, lock the conceptual model. The simplest model that survives real-world change looks like this:
Layer 1: Raw events (immutable)
Every click, registration, deposit, wager, and reversal is logged as an immutable event with timestamp, player ID, affiliate ID, click ID, amounts, and metadata. Raw events are append-only. If something changes, you add a new event—you don’t rewrite history.
Layer 2: Attribution state (calculated)
This is where business logic lives: which affiliate gets credit, which commission rate applies, what “qualified” means, how reversals/holds apply, and what the current attributed LTV is. This layer gets recalculated when rules change.
Layer 3: Reporting aggregates (optimized)
Pre-calculated rollups for dashboards: daily revenue by affiliate, cohort retention curves, payout accrual vs paid, and ROI by channel. These refresh hourly/daily and exist for speed—not truth.
Most operators accidentally mix these layers (e.g., storing calculated commission next to raw events), then can’t reprocess when they discover a mapping or definition mistake. Separate the layers. Keep raw events forever. Recalculate attribution when needed. Refresh aggregates for speed.
What data you actually need to export (minimum viable tables)
Below is the minimum dataset your BI team needs from your affiliate system to build reliable joins and profitability reporting.
Clicks (raw events)
| Field | Type | Description | Example |
|---|---|---|---|
| click_id | string | Unique click identifier | clk_a7f3d9e2b4 |
| timestamp | datetime (UTC) | When click occurred | 2026-01-15 14:32:18 |
| affiliate_id | integer | Which affiliate | 12345 |
| offer_id | string/integer | Which offer/promo | offer_welcome_de |
| sub1–sub5 | string | SubID dimensions | twitch / jan-stream / overlay |
| ip_hash | string | IP hashed for privacy | SHA256… |
| user_agent | string | Browser/device info | Mozilla/5.0… |
| geo_country | string | Server-detected country | DE |
| device_type | string | desktop/mobile/tablet | mobile |
| referrer_url | string | Where click came from | review-site.com/best-casinos |
Why this matters: clicks are your attribution evidence chain. When a payout dispute happens (“we sent this player”), you need the raw click record with timestamp and parameters proving how and when the player arrived.
Conversions (multi-event)
| Field | Type | Description | Example |
|---|---|---|---|
| conversion_id | string | Unique conversion record ID | conv_847392 |
| click_id | string | Links back to click | clk_a7f3d9e2b4 |
| player_id | string | Platform player ID | p_847392 |
| affiliate_id | integer | Credited affiliate | 12345 |
| event_type | enum | registration/kyc/ftd/deposit/ngr | first_deposit |
| event_timestamp | datetime (UTC) | When event occurred | 2026-01-15 16:45:22 |
| amount | decimal | Transaction or revenue amount | 200.00 |
| currency | string | ISO currency code | EUR |
| status | enum | pending/approved/rejected | approved |
| commission_amount | decimal | Affiliate earnings for this event | 70.00 |
| commission_currency | string | Payout currency | EUR |
Why this matters: this is your money table. Your BI joins this to clicks (via click_id) and to platform/PSP/CRM (via player_id) to analyze conversion rates, time-to-deposit, cohort quality, and commission ROI by affiliate and SubID.
Player attribution map (click → player)
This table is the glue. It’s where most “we can’t reconcile” projects either succeed or die.
| Field | Type | Description | Example |
|---|---|---|---|
| player_id | string | Platform player ID | p_847392 |
| first_click_id | string | Original click associated with registration | clk_a7f3d9e2b4 |
| attributed_affiliate_id | integer | Affiliate credited per your rules | 12345 |
| attribution_model | string | last-click / position-based / etc. | last_click |
| attribution_window_days | integer | Window used when player converted | 30 |
| created_at | datetime (UTC) | When mapping was created | 2026-01-15 16:40:00 |
Important nuance: click_id is perfect for attribution truth, but platform/PSP systems usually join on player_id. You need a strict click→player mapping captured at registration/FTD so cross-system joins don’t devolve into guesswork.
Player lifetime value (aggregated)
| Field | Type | Description | Example |
|---|---|---|---|
| player_id | string | Platform player ID | p_847392 |
| affiliate_id | integer | Attributed affiliate | 12345 |
| registration_date | date | When player registered | 2026-01-15 |
| first_deposit_date | date | When FTD occurred | 2026-01-15 |
| total_deposits | decimal | Lifetime deposits | 1250.00 |
| total_withdrawals | decimal | Lifetime withdrawals | 420.00 |
| total_ngr | decimal | Lifetime NGR | 830.00 |
| total_commission_paid | decimal | Total commission paid | 290.50 |
| days_active | integer | Days between first and last activity | 87 |
| is_active_30d | boolean | Active in last 30 days | true |
| last_activity_date | date | Most recent login/wager | 2026-04-10 |
Why this matters: it separates “volume” affiliates from “value” affiliates. You can tier commission based on cohort quality instead of being held hostage by FTD counts.
Payouts (financial reconciliation)
| Field | Type | Description | Example |
|---|---|---|---|
| payout_id | string | Unique payout batch ID | payout_202601 |
| affiliate_id | integer | Affiliate paid | 12345 |
| period_start | date | Commission period start | 2026-01-01 |
| period_end | date | Commission period end | 2026-01-31 |
| total_commission | decimal | Total owed | 4280.50 |
| currency | string | Payout currency | EUR |
| status | enum | pending/paid/held | paid |
| paid_date | date | When actually paid | 2026-03-01 |
| payment_method | string | wire/crypto/etc. | wire |
| invoice_id | string | Accounting reference | INV-2026-001 |
Why this matters: finance reconciles commission accrued (from conversions) vs commission paid (from payouts). Discrepancies mean calculation errors, holds, or missing payments.
Export cadence: hourly, daily, or real-time?
Different data have different freshness requirements:
Export hourly
- Raw clicks (useful for fraud/anomaly detection)
- Conversion events (for “today” dashboards)
- Pending commissions (for operational monitoring)
Export daily (end of day UTC)
- Aggregates (daily revenue by affiliate, daily cohort metrics)
- Reconciliation datasets (clicks vs conversions vs platform/PSP totals)
Export weekly/monthly
- Historical rollups (monthly cohort retention, YoY)
- Payout summaries (month-end accounting)
Most operators start with daily warehouse loads, then move to hourly as BI maturity increases. Real-time streaming is optional—and usually only worth it for fraud triggers and live ops dashboards.
File formats and access methods
Choose the simplest method that matches your data volume and BI maturity:
| Method | Best when | Watch-outs |
|---|---|---|
| CSV exports | Lower volumes, file-based workflows, simple pipelines | Easy to break with schema changes; painful at 1M+ rows per export |
| JSON exports | API-first ingestion, rich metadata, modern pipelines | Harder for analysts; needs robust parsing and schema control |
| Direct database read access | High volume, SQL-capable team, near real-time queries | Requires governance; use read replica and access controls |
At scale, the common pattern is: read replica for operational queries + warehouse copy for historical joins (platform + PSP + CRM).
The reconciliation framework (affiliate + platform + PSP)
This is where most BI projects stumble. You have three “truths” that must align:
- Affiliate system: attribution, events, commission calculation
- Gaming platform: wagers, bonus cost, NGR (profitability truth)
- PSP: deposits, withdrawals, settlements (cash movement truth)
Numbers don’t match because definitions and timing don’t match. Here are the most common mismatch types:
| Discrepancy type | Typical cause | Fix |
|---|---|---|
| Affiliate commission > platform profitability | Bonuses/fees not reflected in “revenue” definition used for payout logic | Align to the same NGR definition and document it |
| Platform revenue ≠ PSP deposits | Deposits pending/failed; settlement timing; refunds/chargebacks | Use settled transactions for PSP truth; track timing drift |
| Player count mismatch | ID format drift; duplicates; missing click→player mapping | Standardize player_id and maintain a strict attribution map |
| Time period mismatch | UTC vs local time boundaries; month cutoffs differ | Store everything in UTC; localize only in reporting layer |
The reconciliation pattern: use player_id for cross-system joins, and use click_id (via the attribution map) as your proof chain for affiliate credit.
Example reconciliation query pattern
This example flags affiliates where actual commission rate drift suggests either a definition mismatch (NGR components) or a rule-application issue.
-- Join affiliate conversions to platform revenue by player_id (via your attribution map)
SELECT
am.attributed_affiliate_id AS affiliate_id,
COUNT(DISTINCT am.player_id) AS players,
SUM(ac.commission_amount) AS commission_owed,
SUM(pr.ngr_amount) AS platform_ngr,
(SUM(ac.commission_amount) / NULLIF(SUM(pr.ngr_amount), 0)) AS actual_commission_rate
FROM attribution_map am
JOIN affiliate_conversions ac
ON ac.player_id = am.player_id
LEFT JOIN platform_revenue pr
ON pr.player_id = am.player_id
AND DATE_TRUNC('month', pr.revenue_date) = DATE_TRUNC('month', ac.event_timestamp)
WHERE ac.event_type = 'first_deposit'
AND ac.status = 'approved'
GROUP BY am.attributed_affiliate_id
HAVING ABS((SUM(ac.commission_amount) / NULLIF(SUM(pr.ngr_amount), 0)) - 0.35) > 0.05;
Run this monthly before payouts. If you see drift, you’re either paying on the wrong “revenue” definition, or your rules aren’t being applied consistently across events/currencies/time windows.
Privacy and compliance note (don’t skip this)
Affiliate tracking and BI exports often contain sensitive data. The practical approach is: minimize what you store, hash what you can (e.g., IP), separate PII from analytics tables, and apply strict access controls and retention policies. Your BI should be able to answer profitability questions without exposing personal data to analysts who don’t need it.
Data dictionary template
Every BI integration needs documentation. Use a consistent template so the next person doesn’t reverse-engineer your pipeline at 2 AM.
Table: affiliate_conversions
| Field name | Data type | Null? | Description | Business rules | Example |
|---|---|---|---|---|---|
| conversion_id | VARCHAR(50) | NOT NULL | Unique event ID | Auto-generated; immutable | conv_a7f3d9 |
| click_id | VARCHAR(50) | NULL | Reference to click | NULL if unattributed | clk_b4e2f8 |
| player_id | VARCHAR(50) | NOT NULL | Platform player ID | Must match platform player identifier | p_847392 |
| affiliate_id | INTEGER | NULL | Credited affiliate | NULL if organic/other channel | 12345 |
| event_type | ENUM | NOT NULL | Event classification | registration, kyc_approved, first_deposit, deposit, ngr_daily | first_deposit |
| event_timestamp | TIMESTAMP | NOT NULL | When event occurred | Stored in UTC | 2026-01-15 16:45:22 |
| amount | DECIMAL(10,2) | NULL | Transaction/revenue amount | NULL for registration/KYC | 200.00 |
| currency | CHAR(3) | NOT NULL | ISO currency code | Uppercase | EUR |
| status | ENUM | NOT NULL | Approval status | pending, approved, rejected | approved |
| commission_amount | DECIMAL(10,2) | NULL | Affiliate earnings | Calculated per plan/tier; never negative | 70.00 |
Notes: NGR events may be negative (player wins). Your commission_amount should not go negative unless you explicitly support negative carryover (and if you do, document it loudly).
BI QA checklist (don’t trust dashboards until this passes)
Instead of “checkbox theater,” here’s a QA checklist that catches the real failure modes.
| Check | How to validate | Pass criteria |
|---|---|---|
| Completeness | Compare source vs warehouse counts for clicks and conversions | Row count variance < 0.5% |
| No date gaps | Check daily partitions for missing dates | No missing days in last 90 days |
| Key integrity | Validate player_id exists across platform/PSP where expected | Orphans < 0.1% |
| Commission math | Spot-check 20 random conversions vs plan rules | 0 mismatches |
| Timezone alignment | Verify all stores are UTC; check month boundary events | No boundary drift in reconciliation |
| Deduplication | Force duplicate events in staging and confirm one credit | Exactly one payable conversion per rule |
| Reversals propagate | Create a reversal/chargeback and confirm downstream totals update | Dashboards update within SLA |
| Currency correctness | Verify FX rate source, timestamp, and conversion logic | Consistent FX application across systems |
When you find discrepancies, don’t just “fix the number.” Fix the definition, the mapping, or the pipeline step that created the mismatch.
Common BI integration mistakes (and fixes)
Mistake 1: Treating the affiliate system as the sole source of truth for revenue.
Your affiliate system is the truth for attribution and commission logic. Your gaming platform is the truth for profitability (NGR components). Always reconcile payouts against platform profitability definitions—otherwise you’ll overpay “high volume” sources that are net-negative after bonus cost and fees.
Mistake 2: mixing time zones
If one export is UTC and another is local time, your month-end reconciliation will always be wrong. Store everything in UTC. Convert to local time only in the reporting layer, never in storage.
Mistake 3: Inconsistent player IDs
If one system uses numeric IDs and another prefixes them (or stores them as strings), joins will silently fail. Standardize player_id format in ETL before loading into the warehouse.
Mistake 4: Calculating “LTV” from deposits only
Deposit volume is not profitability. LTV must account for withdrawals, bonus cost, payment fees, chargebacks, and the platform’s NGR logic. If you measure value on gross deposits, you will scale the wrong partners.
Mistake 5: No versioning when rules change
If commission rates or qualification rules change and you overwrite history, your historical reports become unreliable. Store the applied rate and rule version with each payable event (or maintain a ruleset history table) so you can explain payouts retroactively.
How Scaleo supports BI integration without turning it into an engineering project?
Most operators don’t fail because BI is “hard.” They fail because integration becomes a permanent side-quest: scripts that break, schema drift that isn’t documented, and exports that don’t align across systems.

Scaleo is designed to be friendly to BI workflows in three practical ways:
1. Event delivery (push)
For teams that prefer real-time or near real-time ingestion, webhooks can push key events (clicks, conversions, status changes) to your ingestion endpoint. This lets you stream into your pipeline (message bus, ETL service, or your own API) without waiting for manual exports.
2. Programmatic access (pull)
For warehouse loads or backfills, API access enables incremental pulls (e.g., “events since last run”), affiliate metadata sync, and audit queries. This supports reliable reprocessing when you change rules or fix mapping logic.
3. Clean attribution evidence chain
The core requirement for reconciliation is a stable evidence chain from click → player mapping → payable events → payouts. When you can consistently map player_id to the original click_id and attributed affiliate, disputes and reconciliation stop being emotional and start being mechanical.
If you’re evaluating BI readiness, focus on the basics: can you export raw events, maintain a click→player map, track payable events with rule/version context, and reconcile accrual vs paid payouts cleanly? If yes, your BI team can build profitable dashboards with confidence.
The executive dashboard you actually need
Most exec teams don’t want “more charts.” They want answers:
| Executive question | Minimum dashboard metric | Why it matters |
|---|---|---|
| Is affiliate marketing profitable overall? | Affiliate-attributed profitability (platform NGR minus commission and costs) | Stops you scaling volume that is net-negative |
| Which affiliates should we invest in? | LTV and retention by affiliate and SubID cluster | Finds “quiet winners” and exposes churn funnels |
| Are we paying correctly? | Accrued vs paid commission + variance + holds | Prevents payout surprises and finance fire drills |
| What’s our fraud exposure? | Rejected/charged-back rates by source + anomaly flags | Reduces bonus abuse and postback manipulation risk |
Build these four first. Everything else is optimization.
Conclusion: good data beats good guesses
Casino operators make million-euro decisions based on affiliate performance data: which partners to scale, which traffic sources to cut, and how much commission budget to allocate.
If your BI integration is unreliable—if affiliate attribution doesn’t reconcile with platform profitability, if you can’t calculate true LTV by source, if your dashboards show numbers that don’t match reality—you’re making those decisions blind.
The operators who win invest in plumbing early: clean exports, standardized schemas, strict click→player mapping, automated reconciliation, and dashboards that answer business questions without hand-waving.
Build the integration right. Then use the data to out-decide your competitors.
Need help connecting your affiliate data to your BI stack?
Scaleo provides automated exports to BigQuery, Snowflake, and Redshift with pre-built data models and reconciliation frameworks. No custom ETL required.
Schedule a demo to see how we help casino operators build BI integration in days, not months.
🎯 Unlock the full potential of your gambling business
Get actionable insights into your players’ funnel. In-depth reports let you discover your players’ journeys, from clicking on an affiliate link to registration and deposit.