@vouchfor/embeds 0.0.0-experiment.4eb5f06 → 0.0.0-experiment.526750e

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vouchfor/embeds",
3
- "version": "0.0.0-experiment.4eb5f06",
3
+ "version": "0.0.0-experiment.526750e",
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.4eb5f06",
39
+ "@vouchfor/media-player": "0.0.0-experiment.526750e",
40
40
  "uuid": "^9.0.1"
41
41
  },
42
42
  "peerDependencies": {
@@ -51,7 +51,7 @@ class FetcherController {
51
51
  // so to ensure that the cache stays up to date, whenever we detect a cache hit we trigger another
52
52
  // API call with the `Cache-Control` header which will re-fill the cache
53
53
  const resCacheCheck = res?.headers?.get('X-Cache-Check');
54
- if (resCacheCheck && resCacheCheck !== cacheCheck) {
54
+ if (resCacheCheck !== cacheCheck) {
55
55
  fetch(`${embedApiUrl}/vouches/${vouchId}`, {
56
56
  method: 'GET',
57
57
  headers: [
@@ -81,7 +81,7 @@ class FetcherController {
81
81
  // so to ensure that the cache stays up to date, whenever we detect a cache hit we trigger another
82
82
  // API call with the `Cache-Control` header which will re-fill the cache
83
83
  const resCacheCheck = res?.headers?.get('X-Cache-Check');
84
- if (resCacheCheck && resCacheCheck !== cacheCheck) {
84
+ if (resCacheCheck !== cacheCheck) {
85
85
  fetch(`${embedApiUrl}/templates/${templateId}`, {
86
86
  method: 'GET',
87
87
  headers: [
@@ -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 '..';
@@ -14,7 +13,6 @@ type EmbedHost = ReactiveControllerHost & Embed;
14
13
 
15
14
  type TrackingEvent = 'VOUCH_LOADED' | 'VOUCH_RESPONSE_VIEWED' | 'VIDEO_PLAYED' | 'VIDEO_STREAMED';
16
15
  type TrackingPayload = {
17
- vouchId: string;
18
16
  answerId?: string;
19
17
  streamStart?: number;
20
18
  streamEnd?: number;
@@ -38,8 +36,9 @@ class TrackingController implements ReactiveController {
38
36
  private _hasPlayed = false;
39
37
  private _hasLoaded: BooleanMap = {};
40
38
  private _answersViewed: BooleanMap = {};
41
- private _streamedTime: TimeMap = {};
39
+ private _streamStartTime: TimeMap = {};
42
40
  private _streamLatestTime: TimeMap = {};
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: TrackingPayload) => {
134
- const { publicApiUrl } = getEnvUrls(this.host.env);
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,76 +178,57 @@ 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._streamedTime[key] = node.currentTime;
189
+ this._streamStartTime[key] = node.currentTime;
205
190
  this._streamLatestTime[key] = node.currentTime;
206
191
  };
207
192
 
208
193
  private _handleVideoTimeUpdate = ({ detail: { id, key, node } }: CustomEvent<VideoEventDetail>) => {
209
- const vouchId = this._findVouchId();
210
-
211
- if (!vouchId) {
212
- return;
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;
213
198
  }
214
199
 
215
200
  if (
216
- node.currentTime &&
217
201
  !node.paused &&
218
202
  !this.host.paused &&
219
203
  // Only fire the video seeked event when this video is the active one
220
204
  id === this.host.scene?.video?.id &&
221
205
  // Throttle the frequency that we send streamed events while playing
222
- node.currentTime - this._streamedTime[key] > STREAMED_THROTTLE
206
+ this._streamLatestTime[key] - this._streamStartTime[key] > STREAMED_THROTTLE
223
207
  ) {
224
208
  this._sendTrackingEvent('VIDEO_STREAMED', {
225
- vouchId,
226
209
  answerId: id,
227
- streamStart: this._streamedTime[key],
228
- streamEnd: node.currentTime
210
+ streamStart: this._streamStartTime[key],
211
+ streamEnd: this._streamLatestTime[key]
229
212
  });
230
- this._streamedTime[key] = node.currentTime;
231
- }
232
213
 
233
- if (!this.host.paused) {
234
- this._streamLatestTime[key] = node.currentTime;
214
+ this._streamStartTime[key] = node.currentTime;
235
215
  }
236
216
  };
237
217
 
238
218
  private _handleVideoPause = ({ detail: { id, key } }: CustomEvent<VideoEventDetail>) => {
239
- const vouchId = this._findVouchId();
240
-
241
- if (!vouchId) {
242
- return;
243
- }
244
-
245
- // Don't send a tracking event if the video pauses when seeking backwards
246
- if (this._streamLatestTime[key] > this._streamedTime[key] + 0.5) {
219
+ // Don't send a tracking event when seeking backwards
220
+ if (this._streamLatestTime[key] > this._streamStartTime[key]) {
247
221
  // Send a video streamed event any time the video pauses then reset the streamed state
248
222
  // We do this to capture the last bit of time that the video was played between the previous
249
223
  // stream event and the video being paused manually or stopping because it ended
250
224
  this._sendTrackingEvent('VIDEO_STREAMED', {
251
- vouchId,
252
225
  answerId: id,
253
- streamStart: this._streamedTime[key],
226
+ streamStart: this._streamStartTime[key],
254
227
  streamEnd: this._streamLatestTime[key]
255
228
  });
256
229
  }
257
-
258
- delete this._streamedTime[key];
230
+ this._currentlyPlayingVideo = null;
231
+ delete this._streamStartTime[key];
259
232
  delete this._streamLatestTime[key];
260
233
  };
261
234
 
@@ -270,6 +243,20 @@ class TrackingController implements ReactiveController {
270
243
  }
271
244
 
272
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
+
273
260
  this.host.removeEventListener('vouch:loaded', this._handleVouchLoaded);
274
261
  this.host.mediaPlayer?.removeEventListener('play', this._handlePlay);
275
262
  this.host.mediaPlayer?.removeEventListener('video:play', this._handleVideoPlay);