Overview
Grain Analytics includes built-in automatic tracking for:- Heartbeat events: Track session activity to understand user engagement
- Page views: Automatically detect navigation changes
Heartbeat Tracking
Heartbeat tracking monitors user activity and sends periodic events to understand session engagement. This helps you:- Detect active vs. inactive sessions
- Measure session duration accurately
- Identify when users are engaged with your app
Configuration
How It Works
- Activity Detection: Tracks mouse, keyboard, touch, and scroll events
- Smart Intervals:
- Active users: heartbeat every 2 minutes
- Inactive users: heartbeat every 5 minutes
- Automatic: Starts when SDK initializes, stops on destroy
Consent-Aware Behavior
Without Consent (Minimal tracking):Disabling Heartbeat
Automatic Page View Tracking
Page view tracking automatically detects navigation changes in your application, including:- Initial page load
- History API changes (pushState, replaceState)
- Back/forward navigation (popstate)
- Hash changes
Configuration
Framework Support
Works automatically with:- React Router (pushState-based navigation)
- Vue Router (History mode)
- Next.js (App Router and Pages Router)
- Vanilla JS (manual history manipulation)
- Hash-based routing (hashchange events)
Query Parameter Stripping
By default, query parameters are stripped for privacy:Consent-Aware Behavior
Without Consent (Minimal tracking):Disabling Auto Page View
Consent Upgrade Flow
When a user grants consent, the SDK automatically upgrades from minimal to full tracking:- Before Consent: Events use ephemeral session ID (memory-only)
- Consent Granted: SDK fires
_grain_consent_grantedevent with mapping - After Consent: All subsequent events use persistent user ID
Accessing Session Information
Privacy & Compliance
Data Minimization
Before Consent (Opt-in Mode - GDPR Compliant):- ✅ Ephemeral session ID (memory-only JavaScript variable, not persisted anywhere)
- ✅ Page path (no query params)
- ✅ Timestamp
- ✅ Basic heartbeat events (user activity detection)
- ❌ No cookies
- ❌ No localStorage for user identifiers
- ❌ No persistent cross-session identifiers
- ❌ No personal information
- ❌ No referrer or page title
identify()/login() or using JWT auth, persistent identifiers are used for functional/essential purposes.
After Consent:
- ✅ Persistent user ID (stored in localStorage/cookie)
- ✅ Full page URL
- ✅ Referrer, page title
- ✅ Event counts, durations
- ✅ All standard tracking features
Legitimate Interest
Minimal tracking (heartbeat, page views) can be justified under legitimate interest for:- Security: Detect bot activity and abuse
- Service delivery: Ensure application functions properly
- Analytics quality: Basic session metrics for product improvement
Opting Out
Users can disable tracking through consent management:Best Practices
- Use Default Settings: Heartbeat and page view tracking are on by default for good reason
- Strip Query Params: Keep
stripQueryParams: trueto avoid tracking sensitive data - Document in Privacy Policy: Explain what data is collected before and after consent
- Test Consent Flow: Verify that minimal tracking works without consent
- Monitor Session Metrics: Use heartbeat data to understand engagement patterns
Example: Complete Setup
FAQ
Q: Does automatic tracking work in server-side rendering (SSR)?A: No, automatic tracking only works in browser environments. The SDK detects
window and initializes tracking only on the client side.
Q: Can I customize heartbeat intervals?A: Yes, use
heartbeatActiveInterval and heartbeatInactiveInterval config options.
Q: Will automatic tracking slow down my app?A: No. Event listeners are passive and debounced. Heartbeats run on intervals (not per-event). Impact is negligible. Q: How do I track page views in Next.js?
A: It works automatically! No special configuration needed for App Router or Pages Router. Q: Can I disable automatic tracking temporarily?
A: Yes, destroy the client to stop all tracking, or set
enableHeartbeat: false and enableAutoPageView: false during initialization.
Q: What happens to pre-consent events?A: They’re sent with an ephemeral session ID. After consent, the
_grain_consent_granted event allows backend merging if needed.