Skip to content

Commit 48ebb74

Browse files
authored
Merge pull request #496 from dailymotion/improve-viewableImpression-trackers
[tracker] add once feature to viewableImpression tracking
2 parents 125fb7b + c4f5b54 commit 48ebb74

File tree

3 files changed

+75
-19
lines changed

3 files changed

+75
-19
lines changed

docs/api/vast-tracker.md

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -624,7 +624,9 @@ This method should be used when the ad meets criteria for Viewable impression as
624624

625625
#### Parameters
626626

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

629631
#### Event emitted
630632

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

651653
#### Parameters
652654

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

655659
#### Event emitted
656660

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

677681
#### Parameters
678682

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

681687
#### Event emitted
682688

spec/vast_tracker.spec.js

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -851,6 +851,16 @@ describe('VASTTracker', function () {
851851
message: `trackViewableImpression given macros has the wrong type. macros: ${wrongTrackerValue}`,
852852
});
853853
});
854+
855+
it('should not call Viewable URLs if already called', () => {
856+
vastTracker.trackViewableImpression(macros, true);
857+
vastTracker.trackViewableImpression(macros, true);
858+
expect(spyTrackUrl).toHaveBeenCalledWith(
859+
['http://example.com/viewable', 'http://example.com/viewable2'],
860+
macros
861+
);
862+
expect(spyTrackUrl).toHaveBeenCalledTimes(1);
863+
});
854864
});
855865

856866
describe('#trackNotViewableImpression', () => {
@@ -871,6 +881,19 @@ describe('VASTTracker', function () {
871881
message: `trackNotViewableImpression given macros has the wrong type. macros: ${wrongTrackerValue}`,
872882
});
873883
});
884+
885+
it('should not call NotViewable URLs if already called', () => {
886+
vastTracker.trackNotViewableImpression(macros, true);
887+
vastTracker.trackNotViewableImpression(macros, true);
888+
expect(spyTrackUrl).toHaveBeenCalledWith(
889+
[
890+
'http://example.com/notviewable',
891+
'http://example.com/notviewable2',
892+
],
893+
macros
894+
);
895+
expect(spyTrackUrl).toHaveBeenCalledTimes(1);
896+
});
874897
});
875898

876899
describe('#trackUndeterminedImpression', () => {
@@ -891,6 +914,19 @@ describe('VASTTracker', function () {
891914
message: `trackUndeterminedImpression given macros has the wrong type. macros: ${wrongTrackerValue}`,
892915
});
893916
});
917+
918+
it('should not call ViewUndetermined URLs if already called', () => {
919+
vastTracker.trackUndeterminedImpression(macros, true);
920+
vastTracker.trackUndeterminedImpression(macros, true);
921+
expect(spyTrackUrl).toHaveBeenCalledWith(
922+
[
923+
'http://example.com/undertermined',
924+
'http://example.com/undertermined2',
925+
],
926+
macros
927+
);
928+
expect(spyTrackUrl).toHaveBeenCalledTimes(1);
929+
});
894930
});
895931
});
896932

src/vast_tracker.js

Lines changed: 30 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,23 @@ export class VASTTracker extends EventEmitter {
6666
this.trackingEvents[eventName] = events.slice(0);
6767
}
6868

69+
// ViewableImpression node can contain notViewable, viewUndetermined, viewable traking urls
70+
// to benefit the 'once' tracking feature we need to merge them into other trackingEvents
71+
this.viewableImpressionTrackers =
72+
this.ad.viewableImpression?.reduce(
73+
(accumulator, trackers) => {
74+
accumulator.notViewable.push(...trackers.notViewable);
75+
accumulator.viewUndetermined.push(...trackers.viewUndetermined);
76+
accumulator.viewable.push(...trackers.viewable);
77+
return accumulator;
78+
},
79+
{ notViewable: [], viewUndetermined: [], viewable: [] }
80+
) || {};
81+
82+
Object.entries(this.viewableImpressionTrackers).forEach(([key, value]) => {
83+
if (value.length) this.trackingEvents[key] = value;
84+
});
85+
6986
// Nonlinear and companion creatives provide some tracking information at a variation level
7087
// While linear creatives provided that at a creative level. That's why we need to
7188
// differentiate how we retrieve some tracking information.
@@ -394,51 +411,44 @@ export class VASTTracker extends EventEmitter {
394411
* Tracks Viewable impression
395412
* @param {Object} [macros = {}] An optional Object containing macros and their values to be used and replaced in the tracking calls.
396413
*/
397-
trackViewableImpression(macros = {}) {
414+
trackViewableImpression(macros = {}, once = false) {
398415
if (typeof macros !== 'object') {
399416
this.emit('TRACKER-error', {
400417
message: `trackViewableImpression given macros has the wrong type. macros: ${macros}`,
401418
});
402419
return;
403420
}
404-
this.ad.viewableImpression.forEach((impression) => {
405-
this.trackURLs(impression.viewable, macros);
406-
});
421+
422+
this.track('viewable', { macros, once });
407423
}
408424

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

414-
trackNotViewableImpression(macros = {}) {
430+
trackNotViewableImpression(macros = {}, once = false) {
415431
if (typeof macros !== 'object') {
416432
this.emit('TRACKER-error', {
417433
message: `trackNotViewableImpression given macros has the wrong type. macros: ${macros}`,
418434
});
419435
return;
420436
}
421-
422-
this.ad.viewableImpression.forEach((impression) => {
423-
this.trackURLs(impression.notViewable, macros);
424-
});
437+
this.track('notViewable', { macros, once });
425438
}
426439

427440
/**
428441
* Tracks ViewUndetermined impression
429442
* @param {Object} [macros = {}] An optional Object containing macros and their values to be used and replaced in the tracking calls.
430443
*/
431-
trackUndeterminedImpression(macros = {}) {
444+
trackUndeterminedImpression(macros = {}, once = false) {
432445
if (typeof macros !== 'object') {
433446
this.emit('TRACKER-error', {
434447
message: `trackUndeterminedImpression given macros has the wrong type. macros: ${macros}`,
435448
});
436449
return;
437450
}
438-
439-
this.ad.viewableImpression.forEach((impression) => {
440-
this.trackURLs(impression.viewUndetermined, macros);
441-
});
451+
this.track('viewUndetermined', { macros, once });
442452
}
443453

444454
/**
@@ -794,7 +804,11 @@ export class VASTTracker extends EventEmitter {
794804

795805
const progressEvents = Object.entries(this.trackingEvents)
796806
.filter(([key]) => key.startsWith('progress-'))
797-
.map(([key, value]) => ({ name: key, time: parseFloat(key.split('-')[1]), urls: value }))
807+
.map(([key, value]) => ({
808+
name: key,
809+
time: parseFloat(key.split('-')[1]),
810+
urls: value,
811+
}))
798812
.filter(({ time }) => time <= eventTime && time > this.progress);
799813

800814
progressEvents.forEach(({ name, urls }) => {
@@ -838,7 +852,7 @@ export class VASTTracker extends EventEmitter {
838852
eventName = 'close';
839853
}
840854

841-
if (eventName.startsWith('progress-') && !eventName.endsWith("%")) {
855+
if (eventName.startsWith('progress-') && !eventName.endsWith('%')) {
842856
this.trackProgressEvents(eventName, macros, once);
843857
}
844858

0 commit comments

Comments
 (0)