Skip to content

Heartbeat ak #485

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 22 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .mocharc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"require": ["babel-core/register"],
"spec": ["tests/unit/*.js"],
"ignore": ["tests/unit/test-utils/**/*.js"],
"timeout": 5000,
"ui": "bdd",
"recursive": false
}
5 changes: 5 additions & 0 deletions .vscode/extensions.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"recommendations": [
"hbenl.vscode-mocha-test-adapter"
]
}
35 changes: 35 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
{
"mochaExplorer.files": "tests/unit/*.js",
"mochaExplorer.require": ["babel-core/register"],
"mochaExplorer.env": {
"BABEL_ENV": "test"
},
"mochaExplorer.timeout": 5000,
"mochaExplorer.ui": "bdd",
"mochaExplorer.mochaPath": "./node_modules/mocha",
"mochaExplorer.logpanel": true,
"mochaExplorer.autoload": true,
"testExplorer.codeLens": true,
"testExplorer.gutterDecoration": true,
"testExplorer.onStart": "retire",
"testExplorer.onReload": "retire",
"cSpell.words": [
"Ashkenas",
"avocat",
"copypasta",
"esque",
"FLUSHON",
"mainsite",
"mixpanelinit",
"mpap",
"mphb",
"mphbf",
"mplib",
"mpso",
"mpus",
"optout",
"sendbeacon",
"superproperties",
"superprops"
]
}
70 changes: 70 additions & 0 deletions doc/readme.io/javascript-full-api-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,76 @@ var has_opted_out = mixpanel.has_opted_out_tracking();
| <span class="mp-arg-type">boolean</span> | current opt-out status |


___
## mixpanel.heartbeat
Client-side aggregation for streaming analytics events like video watch time, podcast listen time, or other continuous interactions. `mixpanel.heartbeat()` is safe to be called in a loop without exploding your event counts.

Heartbeat produces a single event which represents many heartbeats; the event which summarizes all the heartbeats is sent when the user stops sending heartbeats for a configurable timeout period (default 30 seconds) or when the page unloads.

**Note**: Heartbeat data is session-scoped and does not persist across page refreshes. All pending heartbeat events are automatically flushed when the page unloads.

Each summary event automatically tracks:
- `$duration`: Seconds from first to last heartbeat call
- `$heartbeats`: Number of heartbeat calls made
- `$contentId`: The contentId parameter

### Basic Usage:
```javascript
mixpanel.heartbeat('video_watch', 'video_123');
mixpanel.heartbeat('video_watch', 'video_123'); // 10 seconds later
mixpanel.heartbeat('video_watch', 'video_123'); // 30 seconds later
// After 30 seconds of inactivity, the event is flushed:
// {event: 'video_watch', properties: {$contentId: 'video_123', $duration: 40, $heartbeats: 3}}
```

You can also pass additional properties, and options to be aggregated with each heartbeat call. Properties are merged intelligently by type:
- Numbers are added together
- Strings take the latest value
- Objects are merged (latest overwrites)
- Arrays have elements appended

### Examples:

```javascript
// Force immediate flush
mixpanel.heartbeat('podcast_listen', 'episode_123', { platform: 'mobile' }, { forceFlush: true });

// Custom timeout (60 seconds)
mixpanel.heartbeat('video_watch', 'video_123', { quality: 'HD' }, { timeout: 60000 });

// Property aggregation
mixpanel.heartbeat('video_watch', 'video_123', {
bytes: 1024,
interactions: ['play'],
language: 'en'
});

mixpanel.heartbeat('video_watch', 'video_123', {
bytes: 2048, // aggregated: {bytes: 3072}
interactions: ['pause'], // appended: ['play', 'pause']
language: 'fr' // replaced: {language: 'fr'}
});
```

### Auto-Flush Behavior:
Events are automatically flushed when:
- **Time limit reached**: No activity for 30 seconds (or custom timeout)
- **Page unload**: Browser navigation or tab close (uses sendBeacon for reliability)

**Session Scope**: All heartbeat data is stored in memory only and is lost when the page refreshes or navigates away. This design ensures reliable data transmission without cross-page persistence complexity.


| Argument | Type | Description |
| ------------- | ------------- | ----- |
| **event_name** | <span class="mp-arg-type">String</span></br></span><span class="mp-arg-required">required</span> | The name of the event to track |
| **content_id** | <span class="mp-arg-type">String</span></br></span><span class="mp-arg-required">required</span> | Unique identifier for the content being tracked |
| **properties** | <span class="mp-arg-type">Object</span></br></span><span class="mp-arg-optional">optional</span> | Properties to aggregate with existing data |
| **options** | <span class="mp-arg-type">Object</span></br></span><span class="mp-arg-optional">optional</span> | Configuration options |
| **options.timeout** | <span class="mp-arg-type">Number</span></br></span><span class="mp-arg-optional">optional</span> | Timeout in milliseconds (default 30000) |
| **options.forceFlush** | <span class="mp-arg-type">Boolean</span></br></span><span class="mp-arg-optional">optional</span> | Force immediate flush after aggregation |



___
## mixpanel.identify
Identify a user with a unique ID to track user activity across devices, tie a user to their events, and create a user profile. If you never call this method, unique visitors are tracked using a UUID generated the first time they visit the site.
Expand Down
Loading
Loading