Note: The
PageActionevent type is officially deprecated and is no longer maintained. It has been archived in thearchived-masterbranch for historical reference.
The New Relic Video Core library (@newrelic/video-core) is the foundational framework for video trackers in the New Relic ecosystem. It provides the core classes, state management, event harvesting, and data transmission pipeline that player-specific trackers extend. The library supports two harvester pipelines:
- Browser pipeline — ships events to
bam.nr-data.netvia the standard Browser collector (license key auth). Used by web-based players. - Connected-device pipeline — ships events to
mobile-collector.newrelic.comvia the mobile collector. Used by Vega apps and other connected-device platforms.
Events are categorized into four distinct types:
| Event Type | Description |
|---|---|
VideoAction |
Content playback events (play, pause, seek, buffer, etc.) |
VideoAdAction |
Ad-related events (ad start, end, quartile, break, etc.) |
VideoErrorAction |
Error events (content errors, ad errors, crashes) |
VideoCustomAction |
Custom events defined by the integrator |
- Installation
- Quick Start
- Configuration
- Exposed API
- Building a Custom Tracker
- Tracker Methods Reference
- Getter Methods (Override These)
- Quality of Experience (QoE)
- Obfuscation Rules
- Build & Development
- Distribution Formats
- Testing
- Data Model
- License
npm install @newrelic/video-coreOr include directly via UMD:
<script src="dist/umd/nrvideo.min.js"></script>import nrvideo from '@newrelic/video-core';
// 1. Define a custom tracker by extending VideoTracker
class MyPlayerTracker extends nrvideo.VideoTracker {
getTrackerName() { return 'my-player'; }
getSrc() { return this.player.currentSrc; }
getDuration() { return this.player.duration; }
getPlayhead() { return this.player.currentTime; }
getRenditionWidth() { return this.player.videoWidth; }
getRenditionHeight() { return this.player.videoHeight; }
registerListeners() {
this.player.addEventListener('play', () => this.sendRequest());
this.player.addEventListener('playing', () => this.sendStart());
this.player.addEventListener('pause', () => this.sendPause());
this.player.addEventListener('ended', () => this.sendEnd());
this.player.addEventListener('waiting', () => this.sendBufferStart());
this.player.addEventListener('seeking', () => this.sendSeekStart());
this.player.addEventListener('seeked', () => this.sendSeekEnd());
this.player.addEventListener('error', () => this.sendError({
errorName: this.player.error?.message,
errorCode: this.player.error?.code
}));
}
unregisterListeners() {
// Remove all listeners added in registerListeners
}
}
// 2. Configure and register the tracker
const options = {
info: {
licenseKey: 'YOUR_LICENSE_KEY',
beacon: 'bam.nr-data.net',
applicationID: 'YOUR_APPLICATION_ID',
},
};
const player = document.getElementById('myPlayer');
const tracker = new MyPlayerTracker(player, options);
// 3. Add tracker to Core to begin reporting
nrvideo.Core.addTracker(tracker, options);The options object passed to Core.addTracker() consists of two top-level keys: info (credentials and pipeline config) and config (optional behaviour settings).
Obtain your credentials:
- Log in to one.newrelic.com
- Navigate to the video agent onboarding flow
- Copy your credentials:
licenseKey,beacon, andapplicationId
With Application ID and Beacon:
info: {
licenseKey: 'YOUR_LICENSE_KEY', // Required
applicationID: 'YOUR_APPLICATION_ID', // Required
beacon: 'bam.nr-data.net', // Required when applicationID is provided
}With App Name and Region:
info: {
licenseKey: 'YOUR_LICENSE_KEY', // Required
appName: 'My Video App', // Required when no applicationID
region: 'US', // Required when no applicationID — 'US' | 'EU' | 'staging'
}Valid Browser Beacon Endpoints:
| Region | Beacon |
|---|---|
| US | bam.nr-data.net, bam-cell.nr-data.net |
| EU | bam.eu01.nr-data.net |
| Staging | staging-bam-cell.nr-data.net |
| GOV | gov-bam.nr-data.net |
For Amazon Vega (Fire TV / Kepler runtime), import from the /vega subpath. The info object uses applicationToken and endpoint specific to the Vega pipeline, plus an optional deviceInfo block carrying runtime device identity.
Obtain your application token:
- Log in to one.newrelic.com
- Navigate to the video agent onboarding flow
- Copy your
applicationToken(begins withAA...and ends with-NRMA) and youraccountId
info: {
accountId: 'YOUR_ACCOUNT_ID', // Required
applicationToken: 'YOUR_NRMA_TOKEN', // Required — begins "AA…-NRMA"
endpoint: 'US', // Required — 'US' | 'EU' | 'staging' | 'GOV'
deviceInfo: { // Optional — all sub-fields optional
uuid: getDeviceId(),
osVersion: getSystemVersion(),
deviceModel: getModel(),
deviceManufacturer: getBrand(),
osBuild: getBuildIdSync(),
appBuild: getBuildNumber(),
architecture: 'aarch64',
},
}Install the device-info library to source real device attributes at runtime:
npm install @amazon-devices/react-native-device-info --saveimport {
getDeviceId, getSystemVersion, getModel, getBrand,
getBuildIdSync, getBuildNumber,
} from '@amazon-devices/react-native-device-info';
const deviceInfo = {
uuid: getDeviceId(),
osVersion: getSystemVersion(),
deviceModel: getModel(),
deviceManufacturer: getBrand(),
osBuild: getBuildIdSync(), // OS image build
appBuild: getBuildNumber(), // app build number
architecture: 'aarch64',
};All sub-fields are optional — missing values fall back to the SDK defaults. Extra fields are ignored.
| Field | Recommended source | Falls back to |
|---|---|---|
uuid |
getDeviceId() — stable model-code identifier |
"00000000-0000-0000-0000-000000000000" |
osVersion |
getSystemVersion() |
"1.0" |
deviceModel |
getModel() |
"VegaDevice" |
deviceManufacturer |
getBrand() |
"Amazon" |
osBuild |
getBuildIdSync() — OS image build |
"1" |
appBuild |
getBuildNumber() — app build number |
"1" |
architecture |
'aarch64' |
"aarch64" |
osBuildandappBuildare semantically distinct:osBuildis the OS image identifier set by Amazon;appBuildis your app's build number. UsegetBuildIdSync()for the former andgetBuildNumber()for the latter.
Valid Vega Endpoints:
| Value | Routes to |
|---|---|
'US' |
mobile-collector.newrelic.com |
'EU' |
mobile-collector.eu01.nr-data.net |
'staging' |
staging-mobile-collector.newrelic.com |
'GOV' |
gov-mobile-collector.newrelic.com |
| Option | Type | Default | Description |
|---|---|---|---|
qoeIntervalFactor |
number |
2 |
Include QoE aggregate events once every N harvest cycles. Must be a positive integer. QoE events are always sent on the first and final harvest cycles. |
obfuscate |
array |
[] |
Regex-based rules to mask sensitive data before transmission. See Obfuscation Rules. |
All exports are available under the nrvideo namespace (UMD) or as named imports:
import nrvideo from '@newrelic/video-core';
// Available: nrvideo.Core, nrvideo.VideoTracker, nrvideo.Tracker,
// nrvideo.Emitter, nrvideo.VideoTrackerState, nrvideo.Chrono,
// nrvideo.Log, nrvideo.Constants, nrvideo.version,
// nrvideo.NrVideoEventAggregator, nrvideo.RetryQueueHandler,
// nrvideo.OptimizedHttpClient, nrvideo.HarvestScheduler,
// nrvideo.recordEventStatic class managing tracker registration and event dispatch.
| Method | Description |
|---|---|
Core.addTracker(tracker, options) |
Registers a tracker and initializes video analytics config. Starts event reporting. |
Core.removeTracker(tracker) |
Disposes and removes a tracker. Stops its event reporting. |
Core.getTrackers() |
Returns the array of currently registered trackers. |
Core.send(eventType, actionName, data) |
Sends an event to the collector. Called internally by event handlers. |
Core.sendError(att) |
Sends a VideoErrorAction with actionName: "ERROR". For external/app-level errors. |
Base class for video player trackers. Extends Tracker.
| Method | Description |
|---|---|
constructor(player, options) |
Initializes the tracker. Lifecycle: constructor → setOptions → setPlayer → registerListeners. |
setPlayer(player, tag) |
Sets the player and optional DOM element. Calls registerListeners(). |
setOptions(options) |
Configures tracker options (heartbeat, customData, adsTracker, isAd, parentTracker). |
setAdsTracker(tracker) |
Sets a child ad tracker. Ad events are funneled through the parent. |
setUserId(userId) |
Sets a user identifier included as enduser.id in all events. |
setHarvestInterval(interval) |
Updates the harvest cycle interval in milliseconds. |
dispose() |
Stops heartbeat, disposes ad tracker, unregisters listeners, clears references. |
registerListeners() |
Override this. Attach player event listeners and map to send*() methods. |
unregisterListeners() |
Override this. Detach player event listeners. |
getAttributes(att) |
Do NOT override. Collects all video/ad attributes. Use getter methods instead. |
State-changing methods (call these from registerListeners):
| Method | Event Emitted (Content / Ad) | Description |
|---|---|---|
sendPlayerReady(att) |
PLAYER_READY |
Player is initialized and ready. |
sendRequest(att) |
CONTENT_REQUEST / AD_REQUEST |
Playback has been requested. |
sendStart(att) |
CONTENT_START / AD_START |
First frame rendered. Starts heartbeat. |
sendEnd(att) |
CONTENT_END / AD_END |
Playback ended. Stops heartbeat. |
sendPause(att) |
CONTENT_PAUSE / AD_PAUSE |
Playback paused. |
sendResume(att) |
CONTENT_RESUME / AD_RESUME |
Playback resumed. |
sendBufferStart(att) |
CONTENT_BUFFER_START / AD_BUFFER_START |
Buffering started. |
sendBufferEnd(att) |
CONTENT_BUFFER_END / AD_BUFFER_END |
Buffering ended. |
sendSeekStart(att) |
CONTENT_SEEK_START / AD_SEEK_START |
Seek started. |
sendSeekEnd(att) |
CONTENT_SEEK_END / AD_SEEK_END |
Seek ended. |
sendError(att) |
CONTENT_ERROR / AD_ERROR |
Error occurred during playback. |
sendRenditionChanged(att) |
CONTENT_RENDITION_CHANGE / AD_RENDITION_CHANGE |
Stream quality changed. |
sendDownload(att) |
DOWNLOAD |
Download event. Requires att.state. |
sendHeartbeat(att) |
CONTENT_HEARTBEAT / AD_HEARTBEAT |
Sent automatically every 30s (2s for ads). |
sendAdBreakStart(att) |
AD_BREAK_START |
Ad break started (ads only). |
sendAdBreakEnd(att) |
AD_BREAK_END |
Ad break ended (ads only). |
sendAdQuartile(att) |
AD_QUARTILE |
Ad quartile reached. Requires att.quartile. |
sendAdClick(att) |
AD_CLICK |
Ad clicked. Requires att.url. |
sendCustom(actionName, timeSinceAttName, att) |
Custom VideoCustomAction |
Sends a custom event with a timeSince attribute. |
Base class providing heartbeat, custom data, and attribute management. Extends Emitter.
| Method | Description |
|---|---|
setOptions(options) |
Set heartbeat interval, customData, and parentTracker. |
getHeartbeat() |
Returns heartbeat interval in ms. Default: 30000 (content), 2000 (ads). |
startHeartbeat() |
Starts the heartbeat interval. Called automatically on sendStart. |
stopHeartbeat() |
Stops the heartbeat interval. Called automatically on sendEnd. |
getAttributes(att) |
Returns base attributes (trackerName, coreVersion, isBackgroundEvent, etc.). |
sendVideoAction(event, att) |
Emits a VideoAction event. |
sendVideoAdAction(event, att) |
Emits a VideoAdAction event. |
sendVideoErrorAction(event, att) |
Emits a VideoErrorAction event. |
sendVideoCustomAction(event, att) |
Emits a VideoCustomAction event. |
Event system base class.
| Method | Description |
|---|---|
on(event, callback) |
Subscribe to an event. Use '*' to listen to all events. |
off(event, callback) |
Unsubscribe from an event. |
emit(eventType, event, data) |
Emit an event to all subscribers. |
Internal state machine managing view lifecycle, QoE KPIs, and timing.
| Property | Description |
|---|---|
numberOfErrors |
Error count for current view. |
numberOfAds |
Total ads shown. |
numberOfVideos |
Total videos played. |
totalPlaytime |
Content viewing time in ms (excludes pausing, buffering, ads). |
totalAdPlaytime |
Ad viewing time in ms. |
startupTime |
Time from CONTENT_REQUEST to CONTENT_START in ms. |
peakBitrate |
Maximum bitrate observed during playback. |
Utility class for measuring time lapses.
| Method | Description |
|---|---|
start() |
Start the timer. |
stop() |
Stop the timer and return delta. |
getDeltaTime() |
Get elapsed time since start() in ms. |
getDuration() |
Get accumulated duration across multiple start/stop cycles. |
reset() |
Reset all values. |
clone() |
Create a copy of the chrono. |
Static logging utility with configurable levels.
| Method | Description |
|---|---|
Log.error(...msg) |
Log an error. |
Log.warn(...msg) |
Log a warning. |
Log.notice(...msg) |
Log a notice. |
Log.debug(...msg) |
Log a debug message. |
Log.debugCommonVideoEvents(player, extraEvents, report) |
Attach debug listeners for common HTML5 video events. |
Log Levels (set via Log.level):
nrvideo.Log.level = nrvideo.Log.Levels.DEBUG; // ALL, DEBUG, NOTICE, WARNING, ERROR, SILENTGeneral constants (used by both pipelines):
| Constant | Value | Description |
|---|---|---|
Constants.AdPositions |
{ PRE, MID, POST } |
Ad position enum. |
Constants.COLLECTOR |
Object | Browser beacon endpoint URLs by region. |
Constants.VALID_EVENT_TYPES |
Array | ['VideoAction', 'VideoAdAction', 'VideoErrorAction', 'VideoCustomAction'] |
Constants.MAX_PAYLOAD_SIZE |
1048576 |
Maximum payload size (1 MB). |
Constants.MAX_BEACON_SIZE |
61440 |
Maximum beacon size (60 KB). |
Constants.MAX_EVENTS_PER_BATCH |
1000 |
Maximum events per batch. |
Constants.INTERVAL |
10000 |
Default harvest interval (10s). |
Constants.QOE_KPI_KEYS |
Array | KPI field names tracked in QoE aggregates. |
Constants.QOE_AGGREGATE_KEYS |
Array | Metadata field names included in QoE events. |
Connected-device constants (named exports from constants.js, used by the /vega subpath):
| Export | Description |
|---|---|
MOBILE_ENDPOINT |
Production mobile collector URL (mobile-collector.newrelic.com). |
STAGING_MOBILE_ENDPOINT |
Staging mobile collector URL. |
NR_ENDPOINT |
Endpoint region enum: { US, EU, STAGING }. |
DEFAULT_HARVEST_TIME |
Default harvest cadence: 60_000 ms. |
DEFAULT_BUFFER_SIZE |
Default buffer cap: 100 events (informational). |
CD_DATA_TOKENS_PAYLOAD |
/v5/connect request body template (positional 2-tuple). |
CD_DEVICE_INFO |
/v3/data device-identity tuple (default Vega values). |
CD_METADATA |
/v3/data session-metadata object (default Vega values). |
Extend VideoTracker and override getter methods and listener registration:
class MyPlayerTracker extends nrvideo.VideoTracker {
// Required: identify your tracker
getTrackerName() { return 'my-custom-player'; }
getTrackerVersion() { return '1.0.0'; }
// Override getters to return player metadata
getVideoId() { return this.player.getContentId(); }
getTitle() { return this.player.getTitle(); }
getSrc() { return this.player.getSrc(); }
getDuration() { return this.player.getDuration() * 1000; } // in ms
getPlayhead() { return this.player.getCurrentTime() * 1000; }
getBitrate() { return this.player.getCurrentBitrate(); }
getRenditionName() { return this.player.getQualityLabel(); }
getRenditionHeight() { return this.player.getVideoHeight(); }
getRenditionWidth() { return this.player.getVideoWidth(); }
isLive() { return this.player.isLive(); }
isMuted() { return this.player.isMuted(); }
isFullscreen() { return this.player.isFullscreen(); }
getPlayrate() { return this.player.getPlaybackRate(); }
getPlayerName() { return 'My Player'; }
getPlayerVersion() { return this.player.version; }
// Map player events to tracker methods
registerListeners() {
this.player.on('play', () => this.sendRequest());
this.player.on('playing', () => this.sendStart());
this.player.on('pause', () => this.sendPause());
this.player.on('ended', () => this.sendEnd());
this.player.on('waiting', () => this.sendBufferStart());
this.player.on('canplay', () => this.sendBufferEnd());
this.player.on('seeking', () => this.sendSeekStart());
this.player.on('seeked', () => this.sendSeekEnd());
this.player.on('error', (e) => this.sendError({
errorName: e.message,
errorCode: e.code
}));
}
unregisterListeners() {
this.player.off('play');
this.player.off('playing');
// ... remove all listeners
}
}These methods return null by default. Override them in your tracker to provide player-specific data:
| Getter | Attribute Set | Description |
|---|---|---|
getVideoId() |
contentId / adId |
Content or ad identifier. |
getTitle() |
contentTitle / adTitle |
Content or ad title. |
getSrc() |
contentSrc / adSrc |
Media source URL. |
getDuration() |
contentDuration / adDuration |
Duration in ms. |
getPlayhead() |
contentPlayhead / adPlayhead |
Current playback position in ms. |
getBitrate() |
contentBitrate / adBitrate |
Current bitrate in bits/s. |
getManifestBitrate() |
contentManifestBitrate |
Manifest/playlist declared bitrate in bps. |
getSegmentDownloadBitrate() |
contentSegmentDownloadBitrate |
Measured bitrate from segment download in bps. |
getNetworkDownloadBitrate() |
contentNetworkDownloadBitrate |
Network download throughput in bps. |
getRenditionName() |
contentRenditionName / adRenditionName |
Quality label (e.g., "1080p"). |
getRenditionHeight() |
contentRenditionHeight / adRenditionHeight |
Rendition height in px. |
getRenditionWidth() |
contentRenditionWidth / adRenditionWidth |
Rendition width in px. |
isLive() |
contentIsLive |
true if live stream. |
isMuted() |
contentIsMuted / adIsMuted |
true if muted. |
isFullscreen() |
contentIsFullscreen |
true if fullscreen. |
getPlayrate() |
contentPlayrate |
Playback speed (1.0 = normal). |
getLanguage() |
contentLanguage / adLanguage |
Language in locale notation (e.g., en_US). |
getCdn() |
contentCdn / adCdn |
CDN serving the content. |
getFps() |
contentFps / adFps |
Current frames per second. |
isAutoplayed() |
contentIsAutoplayed |
true if autoplayed. |
getPreload() |
contentPreload |
Preload attribute value. |
getPlayerName() |
playerName |
Player name. |
getPlayerVersion() |
playerVersion |
Player version. |
getAdQuartile() |
adQuartile |
Ad quartile (0–4). |
getAdPosition() |
adPosition |
Ad position (pre, mid, post). |
getAdPartner() |
adPartner |
Ad partner (e.g., ima, freewheel). |
getAdCreativeId() |
adCreativeId |
Ad creative identifier. |
QoE tracking is enabled by default. The library tracks and reports QoE KPI metrics as QOE_AGGREGATE events. To disable, set qoeAggregate: false in the config object. The harvest interval multiplier can be configured via qoeIntervalFactor (default: 2).
| KPI | Description |
|---|---|
startupTime |
Time from CONTENT_REQUEST to CONTENT_START in ms. |
peakBitrate |
Maximum bitrate observed during playback. |
averageBitrate |
Playtime-weighted average bitrate in bps. |
totalPlaytime |
Total content viewing time in ms (excludes pausing, buffering, ads). |
totalRebufferingTime |
Total ms spent rebuffering (excludes initial buffering). |
rebufferingRatio |
(totalRebufferingTime / totalPlaytime) × 100. |
hadStartupError |
true if error occurred before CONTENT_START. |
hadPlaybackError |
true if error occurred at any time during playback. |
QoE KPIs are refreshed before each harvest drain and always included in the final harvest at CONTENT_END.
Mask sensitive data in event payloads before transmission using regex-based rules:
config: {
obfuscate: [
{ regex: /\/user\/[^\/?"]+/, replacement: '/user/[REDACTED]' },
{ regex: /token=[^&"]+/, replacement: 'token=[MASKED]' },
]
}| Field | Type | Description |
|---|---|---|
regex |
string | RegExp |
Pattern to match in the serialized JSON payload. |
replacement |
string |
Replacement string for each match. |
Rules are applied sequentially — the output of one rule feeds into the next. Invalid regex patterns are skipped with a warning logged via Log.warn.
# Install dependencies
npm install
# Production build
npm run build
# Development build (unminified)
npm run build:dev
# Watch mode (production)
npm run watch
# Watch mode (development)
npm run watch:dev
# Clean build artifacts
npm run cleanThe build produces multiple output formats including subpath exports for tree-shaking:
| Format | Path | Usage |
|---|---|---|
| UMD | dist/umd/nrvideo.min.js |
<script> tag → window.nrvideo |
| CommonJS | dist/cjs/index.js |
require('@newrelic/video-core') — both pipelines |
| ES Module | dist/esm/index.js |
import nrvideo from '@newrelic/video-core' — both pipelines |
| CJS Browser | dist/cjs/browser/index.js |
require('@newrelic/video-core/browser') — Browser pipeline only |
| CJS Connected-Device | dist/cjs/vega/index.js |
require('@newrelic/video-core/vega') — connected-device pipeline only |
| ESM Browser | dist/esm/browser/index.js |
import ... from '@newrelic/video-core/browser' |
| ESM Connected-Device | dist/esm/vega/index.js |
import ... from '@newrelic/video-core/vega' |
Import the specific subpath to ship only the harvester chain you need. The unused pipeline is tree-shaken from the bundle.
// Browser pipeline only — tree-shakes out the connected-device chain
import nrvideo from '@newrelic/video-core/browser';
// Connected-device pipeline only — tree-shakes out Browser harvester and harvestScheduler
import nrvideo from '@newrelic/video-core/vega';
// Both pipelines — use with the default entry
import nrvideo from '@newrelic/video-core';# Run tests with coverage
npm testTests are written using Jest and located in the test/ directory.
For a comprehensive reference of all event types, attributes, and action names, see DATAMODEL.md.
This project is licensed under the Apache 2.0 License.
Should you need assistance with New Relic products, you are in good hands with several support channels.
If the issue has been confirmed as a bug or is a feature request, please file a GitHub issue.
Support Channels:
- New Relic Documentation: Comprehensive guidance for using our platform
- New Relic Community: The best place to engage in troubleshooting questions
- New Relic University: A range of online training for New Relic users of every level
- New Relic Technical Support: 24/7/365 ticketed support. Read more about our Technical Support Offerings
Additional Resources:
- DATAMODEL.md — Complete event and attribute reference
- DEVELOPING.md — Building and testing instructions
- CONTRIBUTING.md — Contribution guidelines
We encourage your contributions to improve the Video Core JS library! Keep in mind that when you submit your pull request, you'll need to sign the CLA via the click-through using CLA-Assistant. You only have to sign the CLA one time per project.
If you have any questions, or to execute our corporate CLA (which is required if your contribution is on behalf of a company), drop us an email at opensource@newrelic.com.
For more details on how best to contribute, see CONTRIBUTING.md.
As noted in our security policy, New Relic is committed to the privacy and security of our customers and their data. We believe that providing coordinated disclosure by security researchers and engaging with the security community are important means to achieve our security goals.
If you believe you have found a security vulnerability in this project or any of New Relic's products or websites, we welcome and greatly appreciate you reporting it to New Relic through our bug bounty program.
If you would like to contribute to this project, review these guidelines.
To all contributors, we thank you! Without your contribution, this project would not be what it is today.
The Video Core JS library is licensed under the Apache 2.0 License.
The Video Core JS library also uses source code from third-party libraries. Full details on which libraries are used and the terms under which they are licensed can be found in the third-party notices document.