Skip to content
Merged
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
12 changes: 9 additions & 3 deletions docs/api/vast-tracker.md
Original file line number Diff line number Diff line change
Expand Up @@ -624,7 +624,9 @@ This method should be used when the ad meets criteria for Viewable impression as

#### Parameters

- - **`macros: Object`** - Optional parameter. Object containing macros and their values to be replaced. Macros must be supported by VAST specification.
- **`macros: Object`** - Optional parameter. Object containing macros and their values to be replaced. Macros must be supported by VAST specification.
- **`once: Boolean`** - An optional Boolean to define if the event has to be tracked only once. Set to `false` by default


#### Event emitted

Expand All @@ -650,7 +652,9 @@ This method should be used when the ad meets criteria for NotViewable impression

#### Parameters

- - **`macros: Object`** - Optional parameter. Object containing macros and their values to be replaced. Macros must be supported by VAST specification.
- **`macros: Object`** - Optional parameter. Object containing macros and their values to be replaced. Macros must be supported by VAST specification.
- **`once: Boolean`** - An optional Boolean to define if the event has to be tracked only once. Set to `false` by default


#### Event emitted

Expand All @@ -676,7 +680,9 @@ This method should be used when the ad meets criteria for ViewUndetermined impre

#### Parameters

- - **`macros: Object`** - Optional parameter. Object containing macros and their values to be replaced. Macros must be supported by VAST specification.
- **`macros: Object`** - Optional parameter. Object containing macros and their values to be replaced. Macros must be supported by VAST specification.
- **`once: Boolean`** - An optional Boolean to define if the event has to be tracked only once. Set to `false` by default


#### Event emitted

Expand Down
36 changes: 36 additions & 0 deletions spec/vast_tracker.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -851,6 +851,16 @@ describe('VASTTracker', function () {
message: `trackViewableImpression given macros has the wrong type. macros: ${wrongTrackerValue}`,
});
});

it('should not call Viewable URLs if already called', () => {
vastTracker.trackViewableImpression(macros, true);
vastTracker.trackViewableImpression(macros, true);
expect(spyTrackUrl).toHaveBeenCalledWith(
['http://example.com/viewable', 'http://example.com/viewable2'],
macros
);
expect(spyTrackUrl).toHaveBeenCalledTimes(1);
});
});

describe('#trackNotViewableImpression', () => {
Expand All @@ -871,6 +881,19 @@ describe('VASTTracker', function () {
message: `trackNotViewableImpression given macros has the wrong type. macros: ${wrongTrackerValue}`,
});
});

it('should not call NotViewable URLs if already called', () => {
vastTracker.trackNotViewableImpression(macros, true);
vastTracker.trackNotViewableImpression(macros, true);
expect(spyTrackUrl).toHaveBeenCalledWith(
[
'http://example.com/notviewable',
'http://example.com/notviewable2',
],
macros
);
expect(spyTrackUrl).toHaveBeenCalledTimes(1);
});
});

describe('#trackUndeterminedImpression', () => {
Expand All @@ -891,6 +914,19 @@ describe('VASTTracker', function () {
message: `trackUndeterminedImpression given macros has the wrong type. macros: ${wrongTrackerValue}`,
});
});

it('should not call ViewUndetermined URLs if already called', () => {
vastTracker.trackUndeterminedImpression(macros, true);
vastTracker.trackUndeterminedImpression(macros, true);
expect(spyTrackUrl).toHaveBeenCalledWith(
[
'http://example.com/undertermined',
'http://example.com/undertermined2',
],
macros
);
expect(spyTrackUrl).toHaveBeenCalledTimes(1);
});
});
});

Expand Down
46 changes: 30 additions & 16 deletions src/vast_tracker.js
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,23 @@ export class VASTTracker extends EventEmitter {
this.trackingEvents[eventName] = events.slice(0);
}

// ViewableImpression node can contain notViewable, viewUndetermined, viewable traking urls
// to benefit the 'once' tracking feature we need to merge them into other trackingEvents
this.viewableImpressionTrackers =
this.ad.viewableImpression?.reduce(
(accumulator, trackers) => {
accumulator.notViewable.push(...trackers.notViewable);
accumulator.viewUndetermined.push(...trackers.viewUndetermined);
accumulator.viewable.push(...trackers.viewable);
return accumulator;
},
{ notViewable: [], viewUndetermined: [], viewable: [] }
) || {};

Object.entries(this.viewableImpressionTrackers).forEach(([key, value]) => {
if (value.length) this.trackingEvents[key] = value;
});

// Nonlinear and companion creatives provide some tracking information at a variation level
// While linear creatives provided that at a creative level. That's why we need to
// differentiate how we retrieve some tracking information.
Expand Down Expand Up @@ -394,51 +411,44 @@ export class VASTTracker extends EventEmitter {
* Tracks Viewable impression
* @param {Object} [macros = {}] An optional Object containing macros and their values to be used and replaced in the tracking calls.
*/
trackViewableImpression(macros = {}) {
trackViewableImpression(macros = {}, once = false) {
if (typeof macros !== 'object') {
this.emit('TRACKER-error', {
message: `trackViewableImpression given macros has the wrong type. macros: ${macros}`,
});
return;
}
this.ad.viewableImpression.forEach((impression) => {
this.trackURLs(impression.viewable, macros);
});

this.track('viewable', { macros, once });
}

/**
* Tracks NotViewable impression
* @param {Object} [macros = {}] An optional Object containing macros and their values to be used and replaced in the tracking calls.
*/

trackNotViewableImpression(macros = {}) {
trackNotViewableImpression(macros = {}, once = false) {
if (typeof macros !== 'object') {
this.emit('TRACKER-error', {
message: `trackNotViewableImpression given macros has the wrong type. macros: ${macros}`,
});
return;
}

this.ad.viewableImpression.forEach((impression) => {
this.trackURLs(impression.notViewable, macros);
});
this.track('notViewable', { macros, once });
}

/**
* Tracks ViewUndetermined impression
* @param {Object} [macros = {}] An optional Object containing macros and their values to be used and replaced in the tracking calls.
*/
trackUndeterminedImpression(macros = {}) {
trackUndeterminedImpression(macros = {}, once = false) {
if (typeof macros !== 'object') {
this.emit('TRACKER-error', {
message: `trackUndeterminedImpression given macros has the wrong type. macros: ${macros}`,
});
return;
}

this.ad.viewableImpression.forEach((impression) => {
this.trackURLs(impression.viewUndetermined, macros);
});
this.track('viewUndetermined', { macros, once });
}

/**
Expand Down Expand Up @@ -794,7 +804,11 @@ export class VASTTracker extends EventEmitter {

const progressEvents = Object.entries(this.trackingEvents)
.filter(([key]) => key.startsWith('progress-'))
.map(([key, value]) => ({ name: key, time: parseFloat(key.split('-')[1]), urls: value }))
.map(([key, value]) => ({
name: key,
time: parseFloat(key.split('-')[1]),
urls: value,
}))
.filter(({ time }) => time <= eventTime && time > this.progress);

progressEvents.forEach(({ name, urls }) => {
Expand Down Expand Up @@ -838,7 +852,7 @@ export class VASTTracker extends EventEmitter {
eventName = 'close';
}

if (eventName.startsWith('progress-') && !eventName.endsWith("%")) {
if (eventName.startsWith('progress-') && !eventName.endsWith('%')) {
this.trackProgressEvents(eventName, macros, once);
}

Expand Down