@vouchfor/embeds 0.0.0-experiment.853d689 → 0.0.0-experiment.896f0e4
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 +357 -367
- package/dist/es/embeds.js.map +1 -1
- package/dist/iife/embeds.iife.js +93 -89
- package/dist/iife/embeds.iife.js.map +1 -1
- package/package.json +2 -2
- package/src/components/Embed/controllers/fetcher.ts +2 -2
- package/src/components/Embed/controllers/tracking.ts +53 -90
    
        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.896f0e4",
         | 
| 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.896f0e4",
         | 
| 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  | 
| 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  | 
| 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 '..';
         | 
| @@ -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;
         | 
| @@ -48,11 +47,9 @@ class TrackingController implements ReactiveController { | |
| 48 47 |  | 
| 49 48 | 
             
              private _findVouchId() {
         | 
| 50 49 | 
             
                if (this.host.vouch) {
         | 
| 51 | 
            -
                  if ('uuid' in this.host.vouch) {
         | 
| 52 | 
            -
                    return this.host.vouch.uuid;
         | 
| 53 | 
            -
                  }
         | 
| 54 50 | 
             
                  return this.host.vouch.id;
         | 
| 55 51 | 
             
                }
         | 
| 52 | 
            +
                return null;
         | 
| 56 53 | 
             
              }
         | 
| 57 54 |  | 
| 58 55 | 
             
              private _createVisitor = (visitorId: string) => {
         | 
| @@ -130,19 +127,24 @@ class TrackingController implements ReactiveController { | |
| 130 127 | 
             
                };
         | 
| 131 128 | 
             
              };
         | 
| 132 129 |  | 
| 133 | 
            -
              private _sendTrackingEvent = (event: TrackingEvent, payload | 
| 134 | 
            -
                const  | 
| 135 | 
            -
                const { client, tab, request, visitor } = this._getUids();
         | 
| 130 | 
            +
              private _sendTrackingEvent = (event: TrackingEvent, payload?: TrackingPayload) => {
         | 
| 131 | 
            +
                const vouchId = this._findVouchId();
         | 
| 136 132 |  | 
| 137 | 
            -
                if (this.host.disableTracking) {
         | 
| 133 | 
            +
                if (!vouchId || this.host.disableTracking) {
         | 
| 138 134 | 
             
                  return;
         | 
| 139 135 | 
             
                }
         | 
| 140 136 |  | 
| 137 | 
            +
                const { publicApiUrl } = getEnvUrls(this.host.env);
         | 
| 138 | 
            +
                const { client, tab, request, visitor } = this._getUids();
         | 
| 139 | 
            +
             | 
| 141 140 | 
             
                navigator.sendBeacon(
         | 
| 142 141 | 
             
                  `${publicApiUrl}/api/events`,
         | 
| 143 142 | 
             
                  JSON.stringify({
         | 
| 144 143 | 
             
                    event,
         | 
| 145 | 
            -
                    payload | 
| 144 | 
            +
                    payload: {
         | 
| 145 | 
            +
                      vouchId,
         | 
| 146 | 
            +
                      ...payload
         | 
| 147 | 
            +
                    },
         | 
| 146 148 | 
             
                    context: {
         | 
| 147 149 | 
             
                      'x-uid-client': client,
         | 
| 148 150 | 
             
                      'x-uid-tab': tab,
         | 
| @@ -161,125 +163,74 @@ class TrackingController implements ReactiveController { | |
| 161 163 |  | 
| 162 164 | 
             
                // Only send loaded event once per session
         | 
| 163 165 | 
             
                if (!this._hasLoaded[vouchId]) {
         | 
| 164 | 
            -
                  this._sendTrackingEvent('VOUCH_LOADED' | 
| 165 | 
            -
                    vouchId
         | 
| 166 | 
            -
                  });
         | 
| 166 | 
            +
                  this._sendTrackingEvent('VOUCH_LOADED');
         | 
| 167 167 | 
             
                  this._hasLoaded[vouchId] = true;
         | 
| 168 168 | 
             
                }
         | 
| 169 169 | 
             
              };
         | 
| 170 170 |  | 
| 171 171 | 
             
              private _handlePlay = () => {
         | 
| 172 | 
            -
                const vouchId = this._findVouchId();
         | 
| 173 | 
            -
             | 
| 174 | 
            -
                if (!vouchId) {
         | 
| 175 | 
            -
                  return;
         | 
| 176 | 
            -
                }
         | 
| 177 | 
            -
             | 
| 178 172 | 
             
                // Only send the video played event once per session
         | 
| 179 173 | 
             
                if (!this._hasPlayed) {
         | 
| 180 174 | 
             
                  this._sendTrackingEvent('VIDEO_PLAYED', {
         | 
| 181 | 
            -
                    vouchId,
         | 
| 182 175 | 
             
                    streamStart: this.host.currentTime
         | 
| 183 176 | 
             
                  });
         | 
| 184 177 | 
             
                  this._hasPlayed = true;
         | 
| 185 178 | 
             
                }
         | 
| 186 179 | 
             
              };
         | 
| 187 180 |  | 
| 188 | 
            -
              private _handleVideoPlay = ({ detail: { id, node } }: CustomEvent<VideoEventDetail>) => {
         | 
| 189 | 
            -
                const vouchId = this._findVouchId();
         | 
| 190 | 
            -
             | 
| 191 | 
            -
                if (!vouchId) {
         | 
| 192 | 
            -
                  return;
         | 
| 193 | 
            -
                }
         | 
| 194 | 
            -
             | 
| 181 | 
            +
              private _handleVideoPlay = ({ detail: { id, key, node } }: CustomEvent<VideoEventDetail>) => {
         | 
| 195 182 | 
             
                // Only increment play count once per session
         | 
| 196 | 
            -
                if (!this._answersViewed[ | 
| 183 | 
            +
                if (!this._answersViewed[key]) {
         | 
| 197 184 | 
             
                  this._sendTrackingEvent('VOUCH_RESPONSE_VIEWED', {
         | 
| 198 | 
            -
                    vouchId,
         | 
| 199 185 | 
             
                    answerId: id
         | 
| 200 186 | 
             
                  });
         | 
| 201 | 
            -
                  this._answersViewed[ | 
| 187 | 
            +
                  this._answersViewed[key] = true;
         | 
| 202 188 | 
             
                }
         | 
| 203 189 |  | 
| 204 | 
            -
                this. | 
| 205 | 
            -
                this._streamLatestTime[ | 
| 206 | 
            -
                this._streamedPrevTimestamp[id] = Date.now();
         | 
| 190 | 
            +
                this._streamStartTime[key] = node.currentTime;
         | 
| 191 | 
            +
                this._streamLatestTime[key] = node.currentTime;
         | 
| 207 192 | 
             
              };
         | 
| 208 193 |  | 
| 209 | 
            -
              private  | 
| 210 | 
            -
                 | 
| 211 | 
            -
             | 
| 212 | 
            -
             | 
| 213 | 
            -
                   | 
| 194 | 
            +
              private _handleVideoTimeUpdate = ({ detail: { id, key, node } }: CustomEvent<VideoEventDetail>) => {
         | 
| 195 | 
            +
                // We only want to count any time that the video is actually playing
         | 
| 196 | 
            +
                if (!this.host.paused) {
         | 
| 197 | 
            +
                  this._currentlyPlayingVideo = { id, key, node };
         | 
| 198 | 
            +
                  this._streamLatestTime[key] = node.currentTime;
         | 
| 214 199 | 
             
                }
         | 
| 215 200 |  | 
| 216 | 
            -
                if (this._streamLatestTime[id]) {
         | 
| 217 | 
            -
                  this._sendTrackingEvent('VIDEO_STREAMED', {
         | 
| 218 | 
            -
                    vouchId,
         | 
| 219 | 
            -
                    answerId: id,
         | 
| 220 | 
            -
                    streamStart: this._streamedTime[id],
         | 
| 221 | 
            -
                    streamEnd: this._streamLatestTime[id]
         | 
| 222 | 
            -
                  });
         | 
| 223 | 
            -
                }
         | 
| 224 | 
            -
             | 
| 225 | 
            -
                delete this._streamedTime[id];
         | 
| 226 | 
            -
                delete this._streamLatestTime[id];
         | 
| 227 | 
            -
                delete this._streamedPrevTimestamp[id];
         | 
| 228 | 
            -
              };
         | 
| 229 | 
            -
             | 
| 230 | 
            -
              private _handleVideoTimeUpdate = ({ detail: { id, node } }: CustomEvent<VideoEventDetail>) => {
         | 
| 231 | 
            -
                const vouchId = this._findVouchId();
         | 
| 232 | 
            -
             | 
| 233 | 
            -
                if (!vouchId) {
         | 
| 234 | 
            -
                  return;
         | 
| 235 | 
            -
                }
         | 
| 236 | 
            -
             | 
| 237 | 
            -
                const currentTimestamp = Date.now();
         | 
| 238 201 | 
             
                if (
         | 
| 239 | 
            -
                  node.currentTime &&
         | 
| 240 202 | 
             
                  !node.paused &&
         | 
| 241 203 | 
             
                  !this.host.paused &&
         | 
| 242 204 | 
             
                  // Only fire the video seeked event when this video is the active one
         | 
| 243 205 | 
             
                  id === this.host.scene?.video?.id &&
         | 
| 244 206 | 
             
                  // Throttle the frequency that we send streamed events while playing
         | 
| 245 | 
            -
                   | 
| 207 | 
            +
                  this._streamLatestTime[key] - this._streamStartTime[key] > STREAMED_THROTTLE
         | 
| 246 208 | 
             
                ) {
         | 
| 247 209 | 
             
                  this._sendTrackingEvent('VIDEO_STREAMED', {
         | 
| 248 | 
            -
                    vouchId,
         | 
| 249 210 | 
             
                    answerId: id,
         | 
| 250 | 
            -
                    streamStart: this. | 
| 251 | 
            -
                    streamEnd:  | 
| 211 | 
            +
                    streamStart: this._streamStartTime[key],
         | 
| 212 | 
            +
                    streamEnd: this._streamLatestTime[key]
         | 
| 252 213 | 
             
                  });
         | 
| 253 | 
            -
                  this._streamedTime[id] = node.currentTime;
         | 
| 254 | 
            -
                  this._streamedPrevTimestamp[id] = currentTimestamp;
         | 
| 255 | 
            -
                }
         | 
| 256 | 
            -
             | 
| 257 | 
            -
                this._streamLatestTime[id] = node.currentTime;
         | 
| 258 | 
            -
              };
         | 
| 259 214 |  | 
| 260 | 
            -
             | 
| 261 | 
            -
                const vouchId = this._findVouchId();
         | 
| 262 | 
            -
             | 
| 263 | 
            -
                if (!vouchId) {
         | 
| 264 | 
            -
                  return;
         | 
| 215 | 
            +
                  this._streamStartTime[key] = node.currentTime;
         | 
| 265 216 | 
             
                }
         | 
| 217 | 
            +
              };
         | 
| 266 218 |  | 
| 267 | 
            -
             | 
| 268 | 
            -
                 | 
| 219 | 
            +
              private _handleVideoPause = ({ detail: { id, key } }: CustomEvent<VideoEventDetail>) => {
         | 
| 220 | 
            +
                // Don't send a tracking event when seeking backwards
         | 
| 221 | 
            +
                if (this._streamLatestTime[key] > this._streamStartTime[key]) {
         | 
| 269 222 | 
             
                  // Send a video streamed event any time the video pauses then reset the streamed state
         | 
| 270 223 | 
             
                  // We do this to capture the last bit of time that the video was played between the previous
         | 
| 271 224 | 
             
                  // stream event and the video being paused manually or stopping because it ended
         | 
| 272 225 | 
             
                  this._sendTrackingEvent('VIDEO_STREAMED', {
         | 
| 273 | 
            -
                    vouchId,
         | 
| 274 226 | 
             
                    answerId: id,
         | 
| 275 | 
            -
                    streamStart: this. | 
| 276 | 
            -
                    streamEnd:  | 
| 227 | 
            +
                    streamStart: this._streamStartTime[key],
         | 
| 228 | 
            +
                    streamEnd: this._streamLatestTime[key]
         | 
| 277 229 | 
             
                  });
         | 
| 278 230 | 
             
                }
         | 
| 279 | 
            -
             | 
| 280 | 
            -
                delete this. | 
| 281 | 
            -
                delete this._streamLatestTime[ | 
| 282 | 
            -
                delete this._streamedPrevTimestamp[id];
         | 
| 231 | 
            +
                this._currentlyPlayingVideo = null;
         | 
| 232 | 
            +
                delete this._streamStartTime[key];
         | 
| 233 | 
            +
                delete this._streamLatestTime[key];
         | 
| 283 234 | 
             
              };
         | 
| 284 235 |  | 
| 285 236 | 
             
              hostConnected() {
         | 
| @@ -287,17 +238,29 @@ class TrackingController implements ReactiveController { | |
| 287 238 | 
             
                  this.host.addEventListener('vouch:loaded', this._handleVouchLoaded);
         | 
| 288 239 | 
             
                  this.host.mediaPlayer?.addEventListener('play', this._handlePlay);
         | 
| 289 240 | 
             
                  this.host.mediaPlayer?.addEventListener('video:play', this._handleVideoPlay);
         | 
| 290 | 
            -
                  this.host.mediaPlayer?.addEventListener('video:seeking', this._handleVideoSeeking);
         | 
| 291 241 | 
             
                  this.host.mediaPlayer?.addEventListener('video:pause', this._handleVideoPause);
         | 
| 292 242 | 
             
                  this.host.mediaPlayer?.addEventListener('video:timeupdate', this._handleVideoTimeUpdate);
         | 
| 293 243 | 
             
                });
         | 
| 294 244 | 
             
              }
         | 
| 295 245 |  | 
| 296 246 | 
             
              hostDisconnected() {
         | 
| 247 | 
            +
                if (this._currentlyPlayingVideo) {
         | 
| 248 | 
            +
                  const { id, key } = this._currentlyPlayingVideo;
         | 
| 249 | 
            +
                  if (this._streamLatestTime[key] > this._streamStartTime[key]) {
         | 
| 250 | 
            +
                    // Send a video streamed event any time the video pauses then reset the streamed state
         | 
| 251 | 
            +
                    // We do this to capture the last bit of time that the video was played between the previous
         | 
| 252 | 
            +
                    // stream event and the video being paused manually or stopping because it ended
         | 
| 253 | 
            +
                    this._sendTrackingEvent('VIDEO_STREAMED', {
         | 
| 254 | 
            +
                      answerId: id,
         | 
| 255 | 
            +
                      streamStart: this._streamStartTime[key],
         | 
| 256 | 
            +
                      streamEnd: this._streamLatestTime[key]
         | 
| 257 | 
            +
                    });
         | 
| 258 | 
            +
                  }
         | 
| 259 | 
            +
                }
         | 
| 260 | 
            +
             | 
| 297 261 | 
             
                this.host.removeEventListener('vouch:loaded', this._handleVouchLoaded);
         | 
| 298 262 | 
             
                this.host.mediaPlayer?.removeEventListener('play', this._handlePlay);
         | 
| 299 263 | 
             
                this.host.mediaPlayer?.removeEventListener('video:play', this._handleVideoPlay);
         | 
| 300 | 
            -
                this.host.mediaPlayer?.removeEventListener('video:seeking', this._handleVideoSeeking);
         | 
| 301 264 | 
             
                this.host.mediaPlayer?.removeEventListener('video:pause', this._handleVideoPause);
         | 
| 302 265 | 
             
                this.host.mediaPlayer?.removeEventListener('video:timeupdate', this._handleVideoTimeUpdate);
         | 
| 303 266 | 
             
              }
         |