@vouchfor/embeds 0.0.0-experiment.ab40ec5 → 0.0.0-experiment.ace6cf6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/es/components/Embed/controllers/tracking.d.ts +2 -3
- package/dist/es/embeds.js +65 -76
- package/dist/es/embeds.js.map +1 -1
- package/dist/iife/embeds.iife.js +35 -35
- package/dist/iife/embeds.iife.js.map +1 -1
- package/package.json +2 -2
- package/src/components/Embed/controllers/tracking.ts +42 -80
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@vouchfor/embeds",
|
3
|
-
"version": "0.0.0-experiment.
|
3
|
+
"version": "0.0.0-experiment.ace6cf6",
|
4
4
|
"license": "MIT",
|
5
5
|
"author": "Aaron Williams",
|
6
6
|
"main": "dist/es/embeds.js",
|
@@ -36,7 +36,7 @@
|
|
36
36
|
},
|
37
37
|
"dependencies": {
|
38
38
|
"@lit/task": "^1.0.0",
|
39
|
-
"@vouchfor/media-player": "0.0.0-experiment.
|
39
|
+
"@vouchfor/media-player": "0.0.0-experiment.ace6cf6",
|
40
40
|
"uuid": "^9.0.1"
|
41
41
|
},
|
42
42
|
"peerDependencies": {
|
@@ -1,4 +1,3 @@
|
|
1
|
-
/* eslint-disable max-lines */
|
2
1
|
import { v4 as uuidv4 } from 'uuid';
|
3
2
|
|
4
3
|
import type { Embed } from '..';
|
@@ -7,13 +6,13 @@ import type { ReactiveController, ReactiveControllerHost } from 'lit';
|
|
7
6
|
|
8
7
|
import { getEnvUrls } from '~/utils/env';
|
9
8
|
|
10
|
-
|
9
|
+
// In seconds due to checking against node.currentTime
|
10
|
+
const STREAMED_THROTTLE = 10;
|
11
11
|
|
12
12
|
type EmbedHost = ReactiveControllerHost & Embed;
|
13
13
|
|
14
14
|
type TrackingEvent = 'VOUCH_LOADED' | 'VOUCH_RESPONSE_VIEWED' | 'VIDEO_PLAYED' | 'VIDEO_STREAMED';
|
15
15
|
type TrackingPayload = {
|
16
|
-
vouchId: string;
|
17
16
|
answerId?: string;
|
18
17
|
streamStart?: number;
|
19
18
|
streamEnd?: number;
|
@@ -37,9 +36,9 @@ class TrackingController implements ReactiveController {
|
|
37
36
|
private _hasPlayed = false;
|
38
37
|
private _hasLoaded: BooleanMap = {};
|
39
38
|
private _answersViewed: BooleanMap = {};
|
40
|
-
private
|
39
|
+
private _streamStartTime: TimeMap = {};
|
41
40
|
private _streamLatestTime: TimeMap = {};
|
42
|
-
private
|
41
|
+
private _currentlyPlayingVideo: VideoEventDetail | null = null;
|
43
42
|
|
44
43
|
constructor(host: EmbedHost) {
|
45
44
|
this.host = host;
|
@@ -130,14 +129,16 @@ class TrackingController implements ReactiveController {
|
|
130
129
|
};
|
131
130
|
};
|
132
131
|
|
133
|
-
private _sendTrackingEvent = (event: TrackingEvent, payload
|
134
|
-
const
|
135
|
-
const { client, tab, request, visitor } = this._getUids();
|
132
|
+
private _sendTrackingEvent = (event: TrackingEvent, payload?: TrackingPayload) => {
|
133
|
+
const vouchId = this._findVouchId();
|
136
134
|
|
137
|
-
if (this.host.disableTracking) {
|
135
|
+
if (!vouchId || this.host.disableTracking) {
|
138
136
|
return;
|
139
137
|
}
|
140
138
|
|
139
|
+
const { publicApiUrl } = getEnvUrls(this.host.env);
|
140
|
+
const { client, tab, request, visitor } = this._getUids();
|
141
|
+
|
141
142
|
navigator.sendBeacon(
|
142
143
|
`${publicApiUrl}/api/events`,
|
143
144
|
JSON.stringify({
|
@@ -161,24 +162,15 @@ class TrackingController implements ReactiveController {
|
|
161
162
|
|
162
163
|
// Only send loaded event once per session
|
163
164
|
if (!this._hasLoaded[vouchId]) {
|
164
|
-
this._sendTrackingEvent('VOUCH_LOADED'
|
165
|
-
vouchId
|
166
|
-
});
|
165
|
+
this._sendTrackingEvent('VOUCH_LOADED');
|
167
166
|
this._hasLoaded[vouchId] = true;
|
168
167
|
}
|
169
168
|
};
|
170
169
|
|
171
170
|
private _handlePlay = () => {
|
172
|
-
const vouchId = this._findVouchId();
|
173
|
-
|
174
|
-
if (!vouchId) {
|
175
|
-
return;
|
176
|
-
}
|
177
|
-
|
178
171
|
// Only send the video played event once per session
|
179
172
|
if (!this._hasPlayed) {
|
180
173
|
this._sendTrackingEvent('VIDEO_PLAYED', {
|
181
|
-
vouchId,
|
182
174
|
streamStart: this.host.currentTime
|
183
175
|
});
|
184
176
|
this._hasPlayed = true;
|
@@ -186,100 +178,58 @@ class TrackingController implements ReactiveController {
|
|
186
178
|
};
|
187
179
|
|
188
180
|
private _handleVideoPlay = ({ detail: { id, key, node } }: CustomEvent<VideoEventDetail>) => {
|
189
|
-
const vouchId = this._findVouchId();
|
190
|
-
|
191
|
-
if (!vouchId) {
|
192
|
-
return;
|
193
|
-
}
|
194
|
-
|
195
181
|
// Only increment play count once per session
|
196
182
|
if (!this._answersViewed[key]) {
|
197
183
|
this._sendTrackingEvent('VOUCH_RESPONSE_VIEWED', {
|
198
|
-
vouchId,
|
199
184
|
answerId: id
|
200
185
|
});
|
201
186
|
this._answersViewed[key] = true;
|
202
187
|
}
|
203
188
|
|
204
|
-
this.
|
189
|
+
this._streamStartTime[key] = node.currentTime;
|
205
190
|
this._streamLatestTime[key] = node.currentTime;
|
206
|
-
this._streamedPrevTimestamp[key] = Date.now();
|
207
|
-
};
|
208
|
-
|
209
|
-
private _handleVideoSeeking = ({ detail: { id, key } }: CustomEvent<VideoEventDetail>) => {
|
210
|
-
const vouchId = this._findVouchId();
|
211
|
-
|
212
|
-
if (!vouchId) {
|
213
|
-
return;
|
214
|
-
}
|
215
|
-
|
216
|
-
if (this._streamLatestTime[key]) {
|
217
|
-
this._sendTrackingEvent('VIDEO_STREAMED', {
|
218
|
-
vouchId,
|
219
|
-
answerId: id,
|
220
|
-
streamStart: this._streamedTime[key],
|
221
|
-
streamEnd: this._streamLatestTime[key]
|
222
|
-
});
|
223
|
-
}
|
224
|
-
|
225
|
-
delete this._streamedTime[key];
|
226
|
-
delete this._streamLatestTime[key];
|
227
|
-
delete this._streamedPrevTimestamp[key];
|
228
191
|
};
|
229
192
|
|
230
193
|
private _handleVideoTimeUpdate = ({ detail: { id, key, node } }: CustomEvent<VideoEventDetail>) => {
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
194
|
+
// We only want to count any time that the video is actually playing
|
195
|
+
if (!this.host.paused) {
|
196
|
+
this._currentlyPlayingVideo = { id, key, node };
|
197
|
+
this._streamLatestTime[key] = node.currentTime;
|
235
198
|
}
|
236
199
|
|
237
|
-
const currentTimestamp = Date.now();
|
238
200
|
if (
|
239
|
-
node.currentTime &&
|
240
201
|
!node.paused &&
|
241
202
|
!this.host.paused &&
|
242
203
|
// Only fire the video seeked event when this video is the active one
|
243
204
|
id === this.host.scene?.video?.id &&
|
244
205
|
// Throttle the frequency that we send streamed events while playing
|
245
|
-
|
206
|
+
this._streamLatestTime[key] - this._streamStartTime[key] > STREAMED_THROTTLE
|
246
207
|
) {
|
247
208
|
this._sendTrackingEvent('VIDEO_STREAMED', {
|
248
|
-
vouchId,
|
249
209
|
answerId: id,
|
250
|
-
streamStart: this.
|
251
|
-
streamEnd:
|
210
|
+
streamStart: this._streamStartTime[key],
|
211
|
+
streamEnd: this._streamLatestTime[key]
|
252
212
|
});
|
253
|
-
this._streamedTime[key] = node.currentTime;
|
254
|
-
this._streamedPrevTimestamp[key] = currentTimestamp;
|
255
|
-
}
|
256
213
|
|
257
|
-
|
258
|
-
};
|
259
|
-
|
260
|
-
private _handleVideoPause = ({ detail: { id, key, node } }: CustomEvent<VideoEventDetail>) => {
|
261
|
-
const vouchId = this._findVouchId();
|
262
|
-
|
263
|
-
if (!vouchId) {
|
264
|
-
return;
|
214
|
+
this._streamStartTime[key] = node.currentTime;
|
265
215
|
}
|
216
|
+
};
|
266
217
|
|
267
|
-
|
268
|
-
|
218
|
+
private _handleVideoPause = ({ detail: { id, key } }: CustomEvent<VideoEventDetail>) => {
|
219
|
+
// Don't send a tracking event when seeking backwards
|
220
|
+
if (this._streamLatestTime[key] > this._streamStartTime[key]) {
|
269
221
|
// Send a video streamed event any time the video pauses then reset the streamed state
|
270
222
|
// We do this to capture the last bit of time that the video was played between the previous
|
271
223
|
// stream event and the video being paused manually or stopping because it ended
|
272
224
|
this._sendTrackingEvent('VIDEO_STREAMED', {
|
273
|
-
vouchId,
|
274
225
|
answerId: id,
|
275
|
-
streamStart: this.
|
276
|
-
streamEnd:
|
226
|
+
streamStart: this._streamStartTime[key],
|
227
|
+
streamEnd: this._streamLatestTime[key]
|
277
228
|
});
|
278
229
|
}
|
279
|
-
|
280
|
-
delete this.
|
230
|
+
this._currentlyPlayingVideo = null;
|
231
|
+
delete this._streamStartTime[key];
|
281
232
|
delete this._streamLatestTime[key];
|
282
|
-
delete this._streamedPrevTimestamp[key];
|
283
233
|
};
|
284
234
|
|
285
235
|
hostConnected() {
|
@@ -287,17 +237,29 @@ class TrackingController implements ReactiveController {
|
|
287
237
|
this.host.addEventListener('vouch:loaded', this._handleVouchLoaded);
|
288
238
|
this.host.mediaPlayer?.addEventListener('play', this._handlePlay);
|
289
239
|
this.host.mediaPlayer?.addEventListener('video:play', this._handleVideoPlay);
|
290
|
-
this.host.mediaPlayer?.addEventListener('video:seeking', this._handleVideoSeeking);
|
291
240
|
this.host.mediaPlayer?.addEventListener('video:pause', this._handleVideoPause);
|
292
241
|
this.host.mediaPlayer?.addEventListener('video:timeupdate', this._handleVideoTimeUpdate);
|
293
242
|
});
|
294
243
|
}
|
295
244
|
|
296
245
|
hostDisconnected() {
|
246
|
+
if (this._currentlyPlayingVideo) {
|
247
|
+
const { id, key } = this._currentlyPlayingVideo;
|
248
|
+
if (this._streamLatestTime[key] > this._streamStartTime[key]) {
|
249
|
+
// Send a video streamed event any time the video pauses then reset the streamed state
|
250
|
+
// We do this to capture the last bit of time that the video was played between the previous
|
251
|
+
// stream event and the video being paused manually or stopping because it ended
|
252
|
+
this._sendTrackingEvent('VIDEO_STREAMED', {
|
253
|
+
answerId: id,
|
254
|
+
streamStart: this._streamStartTime[key],
|
255
|
+
streamEnd: this._streamLatestTime[key]
|
256
|
+
});
|
257
|
+
}
|
258
|
+
}
|
259
|
+
|
297
260
|
this.host.removeEventListener('vouch:loaded', this._handleVouchLoaded);
|
298
261
|
this.host.mediaPlayer?.removeEventListener('play', this._handlePlay);
|
299
262
|
this.host.mediaPlayer?.removeEventListener('video:play', this._handleVideoPlay);
|
300
|
-
this.host.mediaPlayer?.removeEventListener('video:seeking', this._handleVideoSeeking);
|
301
263
|
this.host.mediaPlayer?.removeEventListener('video:pause', this._handleVideoPause);
|
302
264
|
this.host.mediaPlayer?.removeEventListener('video:timeupdate', this._handleVideoTimeUpdate);
|
303
265
|
}
|