Tracking
Session Tracking
Event-driven placement session tracking with instant ad KV reporting and focus gating.
Session Tracking
Placement-based session tracking that monitors user engagement and ad fill values with instant event-driven API reporting.
Entry: components/layout/SessionTracker.js
Flow
Heartbeat payload
{
"session_id": "sess_...",
"campaign_id": "23985256456",
"ad_group_id": "197961067837",
"placement": "xyz.com",
"landing_path": "/some-article",
"kv_ads": {
"display-ad-1": { "kv_value": 20 },
"display-ad-2": { "kv_value": 22.5 }
},
"duration": 45,
"current_path": "/current-path",
"is_heartbeat": true
}Key files
| File | Purpose |
|---|---|
lib/utils/sessionTracking.js | Lifecycle, heartbeat, visibility |
lib/utils/sessionApi.js | API requests and payloads |
lib/utils/sessionHelpers.js | localStorage, country, device |
lib/utils/sessionPlacement.js | Placement type normalization |
lib/utils/sessionConstants.js | Keys and endpoints |
components/layout/SessionTracker.js | Client component in root layout |
Placement normalization
Only website subdomains are reduced to the base domain. All other Google Ads placement types are sent unchanged.
| Type | Example | Sent to API |
|---|---|---|
| Website subdomain | blog.site.com | site.com |
| Website domain | site.com | Unchanged |
| Mobile app (modern) | mobileapp::2-com.example.app | Unchanged |
| Mobile app (iOS) | mobileapp::1-123456789 | Unchanged |
| Mobile app (legacy AFM) | 1.android.com.foo.bar.adsenseformobileapps.com | Unchanged |
| Mobile app (legacy AFM) | com.foo.bar.adsenseformobileapps.com | Unchanged |
| Mobile app category | mobileappcategory::69500 | Unchanged |
| Android package | com.example.app | Unchanged |
| YouTube channel | youtube.com::L8ZULXASCc1I_oaOT0NaOQ | Unchanged |
| YouTube video | youtube.com/video/wtLJPvx7-ys | Unchanged |
| Other / non-host | myapp | Unchanged |
Behavior
| Feature | Detail |
|---|---|
| Heartbeat interval | Event-driven (Instant payload on session creation, ad arrival, and exit ping; no recurring 5s/10s pings) |
| Background pause | Tracking & immediate API pings only execute when document is visible AND window is focused |
| Exit ping | pagehide + beforeunload with keepalive: true |
| Display ad tracking | Recorded on slotRenderEnded. Refreshed impressions generate unique keys (slot_r1, slot_r2) so auto-refreshed ads are preserved and never overwritten |
| Interstitial ad tracking | Recorded on slotVisibilityChanged when displayed on screen (inViewPercentage > 0). Preloaded background interstitials are ignored to match GAM impressions 1:1 |
| Rewarded ad tracking | Recorded on onAdReceived after user clicks CTA button and views ad — triggers immediate API ping |
| Domain gating | Runs on every domain (no allowlist) |
| Placement | Subdomains reduced to base domain before API send |