@vouchfor/embeds 0.0.0-experiment.70f6f8d → 0.0.0-experiment.74a768c
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 +3 -2
- package/dist/es/components/Embed/index.d.ts +2 -2
- package/dist/es/embeds.js +360 -362
- package/dist/es/embeds.js.map +1 -1
- package/dist/iife/embeds.iife.js +63 -59
- package/dist/iife/embeds.iife.js.map +1 -1
- package/package.json +2 -2
- package/src/components/Embed/controllers/tracking.ts +66 -69
- package/src/components/Embed/index.ts +3 -2
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.74a768c",
|
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.74a768c",
|
40
40
|
"uuid": "^9.0.1"
|
41
41
|
},
|
42
42
|
"peerDependencies": {
|
@@ -6,13 +6,13 @@ import type { ReactiveController, ReactiveControllerHost } from 'lit';
|
|
6
6
|
|
7
7
|
import { getEnvUrls } from '~/utils/env';
|
8
8
|
|
9
|
-
|
9
|
+
// In seconds due to checking against node.currentTime
|
10
|
+
const STREAMED_THROTTLE = 10;
|
10
11
|
|
11
12
|
type EmbedHost = ReactiveControllerHost & Embed;
|
12
13
|
|
13
14
|
type TrackingEvent = 'VOUCH_LOADED' | 'VOUCH_RESPONSE_VIEWED' | 'VIDEO_PLAYED' | 'VIDEO_STREAMED';
|
14
15
|
type TrackingPayload = {
|
15
|
-
vouchId: string;
|
16
16
|
answerId?: string;
|
17
17
|
streamStart?: number;
|
18
18
|
streamEnd?: number;
|
@@ -36,8 +36,9 @@ class TrackingController implements ReactiveController {
|
|
36
36
|
private _hasPlayed = false;
|
37
37
|
private _hasLoaded: BooleanMap = {};
|
38
38
|
private _answersViewed: BooleanMap = {};
|
39
|
-
private
|
40
|
-
private
|
39
|
+
private _streamStartTime: TimeMap = {};
|
40
|
+
private _streamLatestTime: TimeMap = {};
|
41
|
+
private _currentlyPlayingVideo: VideoEventDetail | null = null;
|
41
42
|
|
42
43
|
constructor(host: EmbedHost) {
|
43
44
|
this.host = host;
|
@@ -128,26 +129,30 @@ class TrackingController implements ReactiveController {
|
|
128
129
|
};
|
129
130
|
};
|
130
131
|
|
131
|
-
private _sendTrackingEvent = (event: TrackingEvent, payload
|
132
|
+
private _sendTrackingEvent = (event: TrackingEvent, payload?: TrackingPayload) => {
|
133
|
+
const vouchId = this._findVouchId();
|
134
|
+
|
135
|
+
if (!vouchId || this.host.disableTracking) {
|
136
|
+
return;
|
137
|
+
}
|
138
|
+
|
132
139
|
const { publicApiUrl } = getEnvUrls(this.host.env);
|
133
140
|
const { client, tab, request, visitor } = this._getUids();
|
134
141
|
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
);
|
150
|
-
}
|
142
|
+
navigator.sendBeacon(
|
143
|
+
`${publicApiUrl}/api/events`,
|
144
|
+
JSON.stringify({
|
145
|
+
event,
|
146
|
+
payload,
|
147
|
+
context: {
|
148
|
+
'x-uid-client': client,
|
149
|
+
'x-uid-tab': tab,
|
150
|
+
'x-uid-request': request,
|
151
|
+
'x-uid-visitor': visitor,
|
152
|
+
'x-reporting-metadata': this._getReportingMetadata()
|
153
|
+
}
|
154
|
+
})
|
155
|
+
);
|
151
156
|
};
|
152
157
|
|
153
158
|
private _handleVouchLoaded = ({ detail: vouchId }: CustomEvent<string>) => {
|
@@ -157,96 +162,74 @@ class TrackingController implements ReactiveController {
|
|
157
162
|
|
158
163
|
// Only send loaded event once per session
|
159
164
|
if (!this._hasLoaded[vouchId]) {
|
160
|
-
this._sendTrackingEvent('VOUCH_LOADED'
|
161
|
-
vouchId
|
162
|
-
});
|
165
|
+
this._sendTrackingEvent('VOUCH_LOADED');
|
163
166
|
this._hasLoaded[vouchId] = true;
|
164
167
|
}
|
165
168
|
};
|
166
169
|
|
167
170
|
private _handlePlay = () => {
|
168
|
-
const vouchId = this._findVouchId();
|
169
|
-
|
170
|
-
if (!vouchId) {
|
171
|
-
return;
|
172
|
-
}
|
173
|
-
|
174
171
|
// Only send the video played event once per session
|
175
172
|
if (!this._hasPlayed) {
|
176
173
|
this._sendTrackingEvent('VIDEO_PLAYED', {
|
177
|
-
vouchId,
|
178
174
|
streamStart: this.host.currentTime
|
179
175
|
});
|
180
176
|
this._hasPlayed = true;
|
181
177
|
}
|
182
178
|
};
|
183
179
|
|
184
|
-
private _handleVideoPlay = ({ detail: { id, node } }: CustomEvent<VideoEventDetail>) => {
|
185
|
-
const vouchId = this._findVouchId();
|
186
|
-
|
187
|
-
if (!vouchId) {
|
188
|
-
return;
|
189
|
-
}
|
180
|
+
private _handleVideoPlay = ({ detail: { id, key, node } }: CustomEvent<VideoEventDetail>) => {
|
190
181
|
// Only increment play count once per session
|
191
|
-
if (!this._answersViewed[
|
182
|
+
if (!this._answersViewed[key]) {
|
192
183
|
this._sendTrackingEvent('VOUCH_RESPONSE_VIEWED', {
|
193
|
-
vouchId,
|
194
184
|
answerId: id
|
195
185
|
});
|
196
|
-
this._answersViewed[
|
186
|
+
this._answersViewed[key] = true;
|
197
187
|
}
|
198
|
-
this._streamedTime[id] = node.currentTime;
|
199
|
-
this._streamedPrevTimestamp[id] = Date.now();
|
200
|
-
};
|
201
188
|
|
202
|
-
|
203
|
-
|
189
|
+
this._streamStartTime[key] = node.currentTime;
|
190
|
+
this._streamLatestTime[key] = node.currentTime;
|
191
|
+
};
|
204
192
|
|
205
|
-
|
206
|
-
|
193
|
+
private _handleVideoTimeUpdate = ({ detail: { id, key, node } }: CustomEvent<VideoEventDetail>) => {
|
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;
|
207
198
|
}
|
208
|
-
|
199
|
+
|
209
200
|
if (
|
210
|
-
node.currentTime &&
|
211
201
|
!node.paused &&
|
212
202
|
!this.host.paused &&
|
213
203
|
// Only fire the video seeked event when this video is the active one
|
214
204
|
id === this.host.scene?.video?.id &&
|
215
205
|
// Throttle the frequency that we send streamed events while playing
|
216
|
-
|
206
|
+
this._streamLatestTime[key] - this._streamStartTime[key] > STREAMED_THROTTLE
|
217
207
|
) {
|
218
208
|
this._sendTrackingEvent('VIDEO_STREAMED', {
|
219
|
-
vouchId,
|
220
209
|
answerId: id,
|
221
|
-
streamStart: this.
|
222
|
-
streamEnd:
|
210
|
+
streamStart: this._streamStartTime[key],
|
211
|
+
streamEnd: this._streamLatestTime[key]
|
223
212
|
});
|
224
|
-
this._streamedTime[id] = node.currentTime;
|
225
|
-
this._streamedPrevTimestamp[id] = currentTimestamp;
|
226
|
-
}
|
227
|
-
};
|
228
213
|
|
229
|
-
|
230
|
-
const vouchId = this._findVouchId();
|
231
|
-
|
232
|
-
if (!vouchId) {
|
233
|
-
return;
|
214
|
+
this._streamStartTime[key] = node.currentTime;
|
234
215
|
}
|
216
|
+
};
|
235
217
|
|
236
|
-
|
237
|
-
|
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]) {
|
238
221
|
// Send a video streamed event any time the video pauses then reset the streamed state
|
239
222
|
// We do this to capture the last bit of time that the video was played between the previous
|
240
223
|
// stream event and the video being paused manually or stopping because it ended
|
241
224
|
this._sendTrackingEvent('VIDEO_STREAMED', {
|
242
|
-
vouchId,
|
243
225
|
answerId: id,
|
244
|
-
streamStart: this.
|
245
|
-
streamEnd:
|
226
|
+
streamStart: this._streamStartTime[key],
|
227
|
+
streamEnd: this._streamLatestTime[key]
|
246
228
|
});
|
247
229
|
}
|
248
|
-
|
249
|
-
delete this.
|
230
|
+
this._currentlyPlayingVideo = null;
|
231
|
+
delete this._streamStartTime[key];
|
232
|
+
delete this._streamLatestTime[key];
|
250
233
|
};
|
251
234
|
|
252
235
|
hostConnected() {
|
@@ -260,6 +243,20 @@ class TrackingController implements ReactiveController {
|
|
260
243
|
}
|
261
244
|
|
262
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
|
+
|
263
260
|
this.host.removeEventListener('vouch:loaded', this._handleVouchLoaded);
|
264
261
|
this.host.mediaPlayer?.removeEventListener('play', this._handlePlay);
|
265
262
|
this.host.mediaPlayer?.removeEventListener('video:play', this._handleVideoPlay);
|
@@ -17,7 +17,7 @@ import '@vouchfor/media-player';
|
|
17
17
|
type EmbedProps = Pick<MediaPlayerProps, 'data' | 'aspectRatio' | 'preload' | 'autoplay' | 'controls'> & {
|
18
18
|
env: Environment;
|
19
19
|
apiKey: string;
|
20
|
-
|
20
|
+
disableTracking?: boolean;
|
21
21
|
trackingSource?: string;
|
22
22
|
vouchId?: string;
|
23
23
|
templateId?: string;
|
@@ -33,7 +33,7 @@ class Embed extends LitElement {
|
|
33
33
|
|
34
34
|
@property({ type: String }) env: EmbedProps['env'] = 'prod';
|
35
35
|
@property({ type: String }) apiKey: EmbedProps['apiKey'] = '';
|
36
|
-
@property({ type: Boolean })
|
36
|
+
@property({ type: Boolean }) disableTracking: EmbedProps['disableTracking'] = false;
|
37
37
|
@property({ type: String }) trackingSource: EmbedProps['trackingSource'] = 'embed';
|
38
38
|
|
39
39
|
@property({ type: Array }) controls: EmbedProps['controls'];
|
@@ -59,6 +59,7 @@ class Embed extends LitElement {
|
|
59
59
|
'waiting',
|
60
60
|
|
61
61
|
'video:loadeddata',
|
62
|
+
'video:seeking',
|
62
63
|
'video:seeked',
|
63
64
|
'video:play',
|
64
65
|
'video:playing',
|