@adobe/alloy 2.19.2 → 2.20.0-alpha.1
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/libEs5/components/Identity/index.js +1 -2
- package/libEs5/components/Identity/injectAddQueryStringIdentityToPayload.js +0 -4
- package/libEs5/components/Identity/injectAwaitIdentityCookie.js +11 -7
- package/libEs5/components/Identity/injectEnsureSingleIdentity.js +3 -6
- package/libEs5/components/LegacyMediaAnalytics/createMediaAnalyticsTracker.js +272 -0
- package/libEs5/components/LegacyMediaAnalytics/createMediaHelper.js +188 -0
- package/libEs5/components/LegacyMediaAnalytics/index.js +48 -0
- package/libEs5/components/LegacyMediaAnalytics/media/constants.js +154 -0
- package/libEs5/components/LegacyMediaAnalytics/media/mediaKeysToXdmConverter.js +51 -0
- package/libEs5/components/MediaCollection/constants/eventTypes.js +25 -0
- package/libEs5/components/MediaCollection/createHeartbeatEngine.js +63 -0
- package/libEs5/components/MediaCollection/createMediaEventManager.js +109 -0
- package/libEs5/components/MediaCollection/createMediaRequest.js +30 -0
- package/libEs5/components/MediaCollection/createMediaSessionCacheManager.js +62 -0
- package/libEs5/components/MediaCollection/createUpdateMediaSessionState.js +31 -0
- package/libEs5/components/MediaCollection/index.js +165 -0
- package/libEs5/components/MediaCollection/validateMediaEventOptions.js +35 -0
- package/libEs5/components/MediaCollection/validateMediaSessionOptions.js +36 -0
- package/libEs5/components/Personalization/createFetchDataHandler.js +1 -4
- package/libEs5/components/Personalization/createNotificationHandler.js +2 -8
- package/libEs5/components/Personalization/createOnDecisionHandler.js +1 -1
- package/libEs5/constants/libraryVersion.js +1 -1
- package/libEs5/core/componentCreators.js +3 -1
- package/libEs5/core/edgeNetwork/injectSendEdgeNetworkRequest.js +1 -1
- package/libEs5/utils/debounce.js +30 -0
- package/libEs5/utils/request/createRequest.js +8 -1
- package/libEs5/utils/validation/createMaximumValidator.js +22 -0
- package/libEs5/utils/validation/index.js +11 -1
- package/libEs5/utils/validation/matchesRegexpValidator.js +22 -0
- package/libEs6/components/Identity/index.js +1 -2
- package/libEs6/components/Identity/injectAddQueryStringIdentityToPayload.js +1 -5
- package/libEs6/components/Identity/injectAwaitIdentityCookie.js +11 -7
- package/libEs6/components/Identity/injectEnsureSingleIdentity.js +3 -4
- package/libEs6/components/LegacyMediaAnalytics/createMediaAnalyticsTracker.js +276 -0
- package/libEs6/components/LegacyMediaAnalytics/createMediaHelper.js +186 -0
- package/libEs6/components/LegacyMediaAnalytics/index.js +45 -0
- package/libEs6/components/LegacyMediaAnalytics/media/constants.js +140 -0
- package/libEs6/components/LegacyMediaAnalytics/media/mediaKeysToXdmConverter.js +46 -0
- package/libEs6/components/MediaCollection/constants/eventTypes.js +21 -0
- package/libEs6/components/MediaCollection/createHeartbeatEngine.js +64 -0
- package/libEs6/components/MediaCollection/createMediaEventManager.js +115 -0
- package/libEs6/components/MediaCollection/createMediaRequest.js +28 -0
- package/libEs6/components/MediaCollection/createMediaSessionCacheManager.js +63 -0
- package/libEs6/components/MediaCollection/createUpdateMediaSessionState.js +30 -0
- package/libEs6/components/MediaCollection/index.js +164 -0
- package/libEs6/components/MediaCollection/validateMediaEventOptions.js +32 -0
- package/libEs6/components/MediaCollection/validateMediaSessionOptions.js +34 -0
- package/libEs6/components/Personalization/createFetchDataHandler.js +1 -4
- package/libEs6/components/Personalization/createNotificationHandler.js +2 -6
- package/libEs6/components/Personalization/createOnDecisionHandler.js +1 -1
- package/libEs6/constants/libraryVersion.js +1 -1
- package/libEs6/core/componentCreators.js +3 -1
- package/libEs6/core/edgeNetwork/injectSendEdgeNetworkRequest.js +1 -1
- package/libEs6/utils/debounce.js +22 -0
- package/libEs6/utils/request/createRequest.js +8 -1
- package/libEs6/utils/validation/createMaximumValidator.js +16 -0
- package/libEs6/utils/validation/index.js +11 -1
- package/libEs6/utils/validation/matchesRegexpValidator.js +17 -0
- package/package.json +3 -8
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Copyright 2023 Adobe. All rights reserved.
|
|
3
|
+
This file is licensed to you under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
you may not use this file except in compliance with the License. You may obtain a copy
|
|
5
|
+
of the License at http://www.apache.org/licenses/LICENSE-2.0
|
|
6
|
+
|
|
7
|
+
Unless required by applicable law or agreed to in writing, software distributed under
|
|
8
|
+
the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
|
|
9
|
+
OF ANY KIND, either express or implied. See the License for the specific language
|
|
10
|
+
governing permissions and limitations under the License.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import defer from "../../utils/defer";
|
|
14
|
+
import { AD_METADATA_KEYS as AdMetadataKeys, AUDIO_METADATA_KEYS as AudioMetadataKeys, EVENT as Event, PLAYER_STATE as PlayerState, STREAM_TYPE as StreamType, MEDIA_OBJECT_KEYS as MediaObjectKey, VIDEO_METADATA_KEYS as VideoMetadataKeys, MEDIA_TYPE as MediaType, MEDIA_EVENTS } from "./media/constants";
|
|
15
|
+
import { deepAssign, isEmptyObject, isNumber } from "../../utils";
|
|
16
|
+
import { adsToXdmKeys, mediaToXdmKeys } from "./media/mediaKeysToXdmConverter";
|
|
17
|
+
import createMediaHelper from "./createMediaHelper";
|
|
18
|
+
const convertSessionDetailsMetadataToXDM = contextData => {
|
|
19
|
+
const customMetadata = [];
|
|
20
|
+
const sessionDetails = {};
|
|
21
|
+
Object.keys(contextData).forEach(key => {
|
|
22
|
+
if (mediaToXdmKeys[key]) {
|
|
23
|
+
sessionDetails[mediaToXdmKeys[key]] = contextData[key];
|
|
24
|
+
} else {
|
|
25
|
+
customMetadata.push({
|
|
26
|
+
name: key,
|
|
27
|
+
value: contextData[key]
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
return {
|
|
32
|
+
sessionDetails,
|
|
33
|
+
customMetadata
|
|
34
|
+
};
|
|
35
|
+
};
|
|
36
|
+
const createMediaDetailsObject = ({
|
|
37
|
+
eventType,
|
|
38
|
+
info,
|
|
39
|
+
context
|
|
40
|
+
}) => {
|
|
41
|
+
const mediaDetails = info;
|
|
42
|
+
const customMetadata = [];
|
|
43
|
+
if (context && !isEmptyObject(context)) {
|
|
44
|
+
if (eventType === MEDIA_EVENTS.AdStart) {
|
|
45
|
+
Object.keys(context).forEach(key => {
|
|
46
|
+
if (adsToXdmKeys[key]) {
|
|
47
|
+
mediaDetails.advertisingDetails[mediaToXdmKeys[key]] = context[key];
|
|
48
|
+
} else {
|
|
49
|
+
customMetadata.push({
|
|
50
|
+
name: key,
|
|
51
|
+
value: context[key]
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
} else {
|
|
56
|
+
Object.keys(context).forEach(key => {
|
|
57
|
+
customMetadata.push({
|
|
58
|
+
name: key,
|
|
59
|
+
value: context[key]
|
|
60
|
+
});
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
mediaDetails.customMetadata = customMetadata;
|
|
64
|
+
}
|
|
65
|
+
return mediaDetails;
|
|
66
|
+
};
|
|
67
|
+
const createHeartbeat = ({
|
|
68
|
+
mainPingInterval,
|
|
69
|
+
playerState,
|
|
70
|
+
trackEvent
|
|
71
|
+
}) => {
|
|
72
|
+
// eslint-disable-next-line consistent-return
|
|
73
|
+
return () => {
|
|
74
|
+
const currentTime = Date.now();
|
|
75
|
+
if (Math.abs(currentTime - playerState.latestTriggeredEvent) / 1000 > mainPingInterval) {
|
|
76
|
+
return trackEvent({
|
|
77
|
+
eventType: "ping"
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
};
|
|
82
|
+
const createGetInstance = ({
|
|
83
|
+
config,
|
|
84
|
+
logger,
|
|
85
|
+
mediaEventManager
|
|
86
|
+
}) => {
|
|
87
|
+
const {
|
|
88
|
+
mainPingInterval
|
|
89
|
+
} = config.mediaCollection;
|
|
90
|
+
const trackerState = {
|
|
91
|
+
qoe: null,
|
|
92
|
+
lastPlayhead: 0,
|
|
93
|
+
latestTriggeredEvent: null
|
|
94
|
+
};
|
|
95
|
+
let ticker;
|
|
96
|
+
let deferSession = defer();
|
|
97
|
+
const updateLastTimeEventTriggered = () => {
|
|
98
|
+
trackerState.latestTriggeredEvent = Date.now();
|
|
99
|
+
};
|
|
100
|
+
const getEventType = ({
|
|
101
|
+
eventType
|
|
102
|
+
}) => {
|
|
103
|
+
if (eventType === MEDIA_EVENTS.BufferComplete) {
|
|
104
|
+
return MEDIA_EVENTS.Play;
|
|
105
|
+
}
|
|
106
|
+
return eventType;
|
|
107
|
+
};
|
|
108
|
+
const trackEvent = ({
|
|
109
|
+
eventType,
|
|
110
|
+
mediaDetails
|
|
111
|
+
}) => {
|
|
112
|
+
return deferSession.promise.then(sessionID => {
|
|
113
|
+
const action = getEventType({
|
|
114
|
+
eventType
|
|
115
|
+
});
|
|
116
|
+
const xdm = {
|
|
117
|
+
eventType: `media.${action}`,
|
|
118
|
+
mediaCollection: {
|
|
119
|
+
sessionID,
|
|
120
|
+
playhead: trackerState.lastPlayhead
|
|
121
|
+
}
|
|
122
|
+
};
|
|
123
|
+
deepAssign(xdm.mediaCollection, mediaDetails);
|
|
124
|
+
const event = mediaEventManager.createMediaEvent({
|
|
125
|
+
options: {
|
|
126
|
+
xdm
|
|
127
|
+
}
|
|
128
|
+
});
|
|
129
|
+
return mediaEventManager.trackMediaEvent({
|
|
130
|
+
event,
|
|
131
|
+
action
|
|
132
|
+
}).then(() => {
|
|
133
|
+
updateLastTimeEventTriggered();
|
|
134
|
+
});
|
|
135
|
+
}).catch(error => {
|
|
136
|
+
logger.warn(`An error occurred while sending ${eventType} Media Event.`, error);
|
|
137
|
+
});
|
|
138
|
+
};
|
|
139
|
+
const heartbeatEngine = createHeartbeat({
|
|
140
|
+
mainPingInterval,
|
|
141
|
+
deferSession,
|
|
142
|
+
playerState: trackerState,
|
|
143
|
+
trackEvent
|
|
144
|
+
});
|
|
145
|
+
return {
|
|
146
|
+
trackSessionStart: (mediaObject, contextData = {}) => {
|
|
147
|
+
if (isEmptyObject(mediaObject)) {
|
|
148
|
+
deferSession.reject("invalid media object");
|
|
149
|
+
return {};
|
|
150
|
+
}
|
|
151
|
+
const mediaCollection = {
|
|
152
|
+
playhead: 0
|
|
153
|
+
};
|
|
154
|
+
const {
|
|
155
|
+
sessionDetails,
|
|
156
|
+
customMetadata
|
|
157
|
+
} = convertSessionDetailsMetadataToXDM(contextData);
|
|
158
|
+
deepAssign(mediaCollection, mediaObject, {
|
|
159
|
+
sessionDetails
|
|
160
|
+
}, {
|
|
161
|
+
customMetadata
|
|
162
|
+
});
|
|
163
|
+
const event = mediaEventManager.createMediaSession({
|
|
164
|
+
xdm: {
|
|
165
|
+
mediaCollection
|
|
166
|
+
}
|
|
167
|
+
});
|
|
168
|
+
return mediaEventManager.trackMediaSession({
|
|
169
|
+
event
|
|
170
|
+
}).then(result => {
|
|
171
|
+
updateLastTimeEventTriggered();
|
|
172
|
+
deferSession.resolve(result.sessionId);
|
|
173
|
+
ticker = setInterval(() => {
|
|
174
|
+
heartbeatEngine();
|
|
175
|
+
}, 1000);
|
|
176
|
+
});
|
|
177
|
+
},
|
|
178
|
+
trackPlay: () => {
|
|
179
|
+
return trackEvent({
|
|
180
|
+
eventType: MEDIA_EVENTS.Play
|
|
181
|
+
});
|
|
182
|
+
},
|
|
183
|
+
trackPause: () => {
|
|
184
|
+
return trackEvent({
|
|
185
|
+
eventType: MEDIA_EVENTS.Pause
|
|
186
|
+
});
|
|
187
|
+
},
|
|
188
|
+
trackSessionEnd: () => {
|
|
189
|
+
clearInterval(ticker);
|
|
190
|
+
return trackEvent({
|
|
191
|
+
eventType: MEDIA_EVENTS.SessionEnd
|
|
192
|
+
}).then(() => {
|
|
193
|
+
deferSession = null;
|
|
194
|
+
});
|
|
195
|
+
},
|
|
196
|
+
trackComplete: () => {
|
|
197
|
+
clearInterval(ticker);
|
|
198
|
+
return trackEvent({
|
|
199
|
+
eventType: MEDIA_EVENTS.SessionComplete
|
|
200
|
+
});
|
|
201
|
+
},
|
|
202
|
+
trackError: errorId => {
|
|
203
|
+
logger.info(`trackError(${errorId})`);
|
|
204
|
+
const errorDetails = {
|
|
205
|
+
name: errorId,
|
|
206
|
+
source: "player"
|
|
207
|
+
};
|
|
208
|
+
const mediaDetails = {
|
|
209
|
+
errorDetails
|
|
210
|
+
};
|
|
211
|
+
return trackEvent({
|
|
212
|
+
eventType: MEDIA_EVENTS.SessionEnd,
|
|
213
|
+
mediaDetails
|
|
214
|
+
});
|
|
215
|
+
},
|
|
216
|
+
trackEvent: (eventType, info, context) => {
|
|
217
|
+
if (isEmptyObject(info)) {
|
|
218
|
+
logger.info("invalid media object");
|
|
219
|
+
return {};
|
|
220
|
+
}
|
|
221
|
+
const mediaDetails = createMediaDetailsObject({
|
|
222
|
+
eventType,
|
|
223
|
+
info,
|
|
224
|
+
context
|
|
225
|
+
});
|
|
226
|
+
return trackEvent({
|
|
227
|
+
eventType,
|
|
228
|
+
mediaDetails
|
|
229
|
+
});
|
|
230
|
+
},
|
|
231
|
+
updatePlayhead: time => {
|
|
232
|
+
if (isNumber(time)) {
|
|
233
|
+
trackerState.lastPlayhead = parseInt(time, 10);
|
|
234
|
+
}
|
|
235
|
+
},
|
|
236
|
+
updateQoEObject: qoeObject => {
|
|
237
|
+
if (!qoeObject) {
|
|
238
|
+
return;
|
|
239
|
+
}
|
|
240
|
+
trackerState.qoe = qoeObject;
|
|
241
|
+
},
|
|
242
|
+
destroy: () => {
|
|
243
|
+
logger.info("Destroy called, destroying the tracker");
|
|
244
|
+
clearInterval(ticker);
|
|
245
|
+
deferSession = null;
|
|
246
|
+
}
|
|
247
|
+
};
|
|
248
|
+
};
|
|
249
|
+
export const createMediaAnalyticsTracker = ({
|
|
250
|
+
config,
|
|
251
|
+
logger,
|
|
252
|
+
mediaEventManager
|
|
253
|
+
}) => {
|
|
254
|
+
logger.info("Media Analytics Component was configured");
|
|
255
|
+
const mediaAnalyticsHelper = createMediaHelper({
|
|
256
|
+
logger
|
|
257
|
+
});
|
|
258
|
+
return {
|
|
259
|
+
getInstance: () => {
|
|
260
|
+
return createGetInstance({
|
|
261
|
+
config,
|
|
262
|
+
logger,
|
|
263
|
+
mediaEventManager
|
|
264
|
+
});
|
|
265
|
+
},
|
|
266
|
+
Event,
|
|
267
|
+
MediaType,
|
|
268
|
+
PlayerState,
|
|
269
|
+
StreamType,
|
|
270
|
+
MediaObjectKey,
|
|
271
|
+
VideoMetadataKeys,
|
|
272
|
+
AudioMetadataKeys,
|
|
273
|
+
AdMetadataKeys,
|
|
274
|
+
...mediaAnalyticsHelper
|
|
275
|
+
};
|
|
276
|
+
};
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Copyright 2023 Adobe. All rights reserved.
|
|
3
|
+
This file is licensed to you under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
you may not use this file except in compliance with the License. You may obtain a copy
|
|
5
|
+
of the License at http://www.apache.org/licenses/LICENSE-2.0
|
|
6
|
+
|
|
7
|
+
Unless required by applicable law or agreed to in writing, software distributed under
|
|
8
|
+
the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
|
|
9
|
+
OF ANY KIND, either express or implied. See the License for the specific language
|
|
10
|
+
governing permissions and limitations under the License.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import { number, objectOf, string } from "../../utils/validation";
|
|
14
|
+
export default (({
|
|
15
|
+
logger
|
|
16
|
+
}) => {
|
|
17
|
+
const createMediaObject = (friendlyName, name, length, contentType, streamType) => {
|
|
18
|
+
const mediaObject = {
|
|
19
|
+
friendlyName,
|
|
20
|
+
name,
|
|
21
|
+
length,
|
|
22
|
+
streamType,
|
|
23
|
+
contentType
|
|
24
|
+
};
|
|
25
|
+
const validate = objectOf({
|
|
26
|
+
friendlyName: string().nonEmpty(),
|
|
27
|
+
name: string().nonEmpty(),
|
|
28
|
+
length: number().required(),
|
|
29
|
+
streamType: string().nonEmpty(),
|
|
30
|
+
contentType: string().nonEmpty()
|
|
31
|
+
});
|
|
32
|
+
try {
|
|
33
|
+
const result = validate(mediaObject);
|
|
34
|
+
const sessionDetails = {
|
|
35
|
+
name: result.name,
|
|
36
|
+
friendlyName: result.friendlyName,
|
|
37
|
+
length: result.length,
|
|
38
|
+
streamType: result.streamType,
|
|
39
|
+
contentType: result.contentType
|
|
40
|
+
};
|
|
41
|
+
return {
|
|
42
|
+
sessionDetails
|
|
43
|
+
};
|
|
44
|
+
} catch (error) {
|
|
45
|
+
logger.warn(`An error occurred while creating the Media Object.`, error);
|
|
46
|
+
return {};
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
const createAdBreakObject = (name, position, startTime) => {
|
|
50
|
+
const adBreakObject = {
|
|
51
|
+
friendlyName: name,
|
|
52
|
+
offset: position,
|
|
53
|
+
index: startTime
|
|
54
|
+
};
|
|
55
|
+
const validator = objectOf({
|
|
56
|
+
friendlyName: string().nonEmpty(),
|
|
57
|
+
offset: number(),
|
|
58
|
+
index: number()
|
|
59
|
+
});
|
|
60
|
+
try {
|
|
61
|
+
const result = validator(adBreakObject);
|
|
62
|
+
const advertisingPodDetails = {
|
|
63
|
+
friendlyName: result.friendlyName,
|
|
64
|
+
offset: result.offset,
|
|
65
|
+
index: result.index
|
|
66
|
+
};
|
|
67
|
+
return {
|
|
68
|
+
advertisingPodDetails
|
|
69
|
+
};
|
|
70
|
+
} catch (error) {
|
|
71
|
+
logger.warn(`An error occurred while creating the Ad Break Object.`, error);
|
|
72
|
+
return {};
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
const createAdObject = (name, id, position, length) => {
|
|
76
|
+
const adObject = {
|
|
77
|
+
friendlyName: name,
|
|
78
|
+
name: id,
|
|
79
|
+
podPosition: position,
|
|
80
|
+
length
|
|
81
|
+
};
|
|
82
|
+
const validator = objectOf({
|
|
83
|
+
friendlyName: string().nonEmpty(),
|
|
84
|
+
name: string().nonEmpty(),
|
|
85
|
+
podPosition: number(),
|
|
86
|
+
length: number()
|
|
87
|
+
});
|
|
88
|
+
try {
|
|
89
|
+
const result = validator(adObject);
|
|
90
|
+
const advertisingDetails = {
|
|
91
|
+
friendlyName: result.friendlyName,
|
|
92
|
+
name: result.name,
|
|
93
|
+
podPosition: result.podPosition,
|
|
94
|
+
length: result.length
|
|
95
|
+
};
|
|
96
|
+
return {
|
|
97
|
+
advertisingDetails
|
|
98
|
+
};
|
|
99
|
+
} catch (error) {
|
|
100
|
+
logger.warn(`An error occurred while creating the Advertising Object.`, error);
|
|
101
|
+
return {};
|
|
102
|
+
}
|
|
103
|
+
};
|
|
104
|
+
const createChapterObject = (name, position, length, startTime) => {
|
|
105
|
+
const chapterDetailsObject = {
|
|
106
|
+
friendlyName: name,
|
|
107
|
+
offset: position,
|
|
108
|
+
length,
|
|
109
|
+
index: startTime
|
|
110
|
+
};
|
|
111
|
+
const validator = objectOf({
|
|
112
|
+
friendlyName: string().nonEmpty(),
|
|
113
|
+
offset: number(),
|
|
114
|
+
length: number(),
|
|
115
|
+
index: number()
|
|
116
|
+
});
|
|
117
|
+
try {
|
|
118
|
+
const result = validator(chapterDetailsObject);
|
|
119
|
+
const chapterDetails = {
|
|
120
|
+
friendlyName: result.friendlyName,
|
|
121
|
+
offset: result.offset,
|
|
122
|
+
index: result.index,
|
|
123
|
+
length: result.length
|
|
124
|
+
};
|
|
125
|
+
return {
|
|
126
|
+
chapterDetails
|
|
127
|
+
};
|
|
128
|
+
} catch (error) {
|
|
129
|
+
logger.warn(`An error occurred while creating the Chapter Object.`, error);
|
|
130
|
+
return {};
|
|
131
|
+
}
|
|
132
|
+
};
|
|
133
|
+
const createStateObject = stateName => {
|
|
134
|
+
const STATE_NAME_REGEX = "^[a-zA-Z0-9_]{1,64}$";
|
|
135
|
+
const validator = string().matches(STATE_NAME_REGEX, "This is not a valid state name.");
|
|
136
|
+
try {
|
|
137
|
+
const result = validator(stateName);
|
|
138
|
+
const stateDetails = {
|
|
139
|
+
name: result
|
|
140
|
+
};
|
|
141
|
+
return {
|
|
142
|
+
stateDetails
|
|
143
|
+
};
|
|
144
|
+
} catch (error) {
|
|
145
|
+
logger.warn(`An error occurred while creating the State Object.`, error);
|
|
146
|
+
return {};
|
|
147
|
+
}
|
|
148
|
+
};
|
|
149
|
+
const createQoEObject = (bitrate, droppedFrames, fps, startupTime) => {
|
|
150
|
+
const qoeObject = {
|
|
151
|
+
bitrate,
|
|
152
|
+
droppedFrames,
|
|
153
|
+
fps,
|
|
154
|
+
startupTime
|
|
155
|
+
};
|
|
156
|
+
const validator = objectOf({
|
|
157
|
+
bitrate: number(),
|
|
158
|
+
droppedFrames: number(),
|
|
159
|
+
fps: number(),
|
|
160
|
+
startupTime: number()
|
|
161
|
+
});
|
|
162
|
+
try {
|
|
163
|
+
const result = validator(qoeObject);
|
|
164
|
+
const qoeDetails = {
|
|
165
|
+
bitrate: result.bitrate,
|
|
166
|
+
droppedFrames: result.droppedFrames,
|
|
167
|
+
fps: result.fps,
|
|
168
|
+
startupTime: result.startupTime
|
|
169
|
+
};
|
|
170
|
+
return {
|
|
171
|
+
qoeDetails
|
|
172
|
+
};
|
|
173
|
+
} catch (error) {
|
|
174
|
+
logger.warn(`An error occurred while creating the QOE Object.`, error);
|
|
175
|
+
return {};
|
|
176
|
+
}
|
|
177
|
+
};
|
|
178
|
+
return {
|
|
179
|
+
createMediaObject,
|
|
180
|
+
createAdBreakObject,
|
|
181
|
+
createAdObject,
|
|
182
|
+
createChapterObject,
|
|
183
|
+
createStateObject,
|
|
184
|
+
createQoEObject
|
|
185
|
+
};
|
|
186
|
+
});
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Copyright 2023 Adobe. All rights reserved.
|
|
3
|
+
This file is licensed to you under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
you may not use this file except in compliance with the License. You may obtain a copy
|
|
5
|
+
of the License at http://www.apache.org/licenses/LICENSE-2.0
|
|
6
|
+
|
|
7
|
+
Unless required by applicable law or agreed to in writing, software distributed under
|
|
8
|
+
the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
|
|
9
|
+
OF ANY KIND, either express or implied. See the License for the specific language
|
|
10
|
+
governing permissions and limitations under the License.
|
|
11
|
+
*/
|
|
12
|
+
/* eslint-disable import/no-restricted-paths */
|
|
13
|
+
|
|
14
|
+
import { createMediaAnalyticsTracker } from "./createMediaAnalyticsTracker";
|
|
15
|
+
import createMediaEventManager from "../MediaCollection/createMediaEventManager";
|
|
16
|
+
const createLegacyMediaAnalytics = ({
|
|
17
|
+
eventManager,
|
|
18
|
+
sendEdgeNetworkRequest,
|
|
19
|
+
config,
|
|
20
|
+
logger,
|
|
21
|
+
consent
|
|
22
|
+
}) => {
|
|
23
|
+
const mediaEventManager = createMediaEventManager({
|
|
24
|
+
sendEdgeNetworkRequest,
|
|
25
|
+
config,
|
|
26
|
+
logger,
|
|
27
|
+
consent,
|
|
28
|
+
eventManager
|
|
29
|
+
});
|
|
30
|
+
return {
|
|
31
|
+
commands: {
|
|
32
|
+
getMediaAnalyticsTracker: {
|
|
33
|
+
run: () => {
|
|
34
|
+
return createMediaAnalyticsTracker({
|
|
35
|
+
config,
|
|
36
|
+
logger,
|
|
37
|
+
mediaEventManager
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
};
|
|
44
|
+
createLegacyMediaAnalytics.namespace = "Legacy Media Analytics";
|
|
45
|
+
export default createLegacyMediaAnalytics;
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Copyright 2023 Adobe. All rights reserved.
|
|
3
|
+
This file is licensed to you under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
you may not use this file except in compliance with the License. You may obtain a copy
|
|
5
|
+
of the License at http://www.apache.org/licenses/LICENSE-2.0
|
|
6
|
+
|
|
7
|
+
Unless required by applicable law or agreed to in writing, software distributed under
|
|
8
|
+
the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
|
|
9
|
+
OF ANY KIND, either express or implied. See the License for the specific language
|
|
10
|
+
governing permissions and limitations under the License.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
export const MEDIA_TYPE = {
|
|
14
|
+
Video: "video",
|
|
15
|
+
Audio: "audio"
|
|
16
|
+
};
|
|
17
|
+
export const STREAM_TYPE = {
|
|
18
|
+
VOD: "vod",
|
|
19
|
+
Live: "live",
|
|
20
|
+
Linear: "linear",
|
|
21
|
+
Podcast: "podcast",
|
|
22
|
+
Audiobook: "audiobook",
|
|
23
|
+
AOD: "aod"
|
|
24
|
+
};
|
|
25
|
+
export const PLAYER_STATE = {
|
|
26
|
+
FullScreen: "fullScreen",
|
|
27
|
+
ClosedCaption: "closedCaptioning",
|
|
28
|
+
Mute: "mute",
|
|
29
|
+
PictureInPicture: "pictureInPicture",
|
|
30
|
+
InFocus: "inFocus"
|
|
31
|
+
};
|
|
32
|
+
export const EVENT = {
|
|
33
|
+
/**
|
|
34
|
+
* Constant defining event type for AdBreak start
|
|
35
|
+
*/
|
|
36
|
+
AdBreakStart: "adBreakStart",
|
|
37
|
+
/**
|
|
38
|
+
* Constant defining event type for AdBreak complete
|
|
39
|
+
*/
|
|
40
|
+
AdBreakComplete: "adBreakComplete",
|
|
41
|
+
/**
|
|
42
|
+
* Constant defining event type for Ad start
|
|
43
|
+
*/
|
|
44
|
+
AdStart: "adStart",
|
|
45
|
+
/**
|
|
46
|
+
* Constant defining event type for Ad complete
|
|
47
|
+
*/
|
|
48
|
+
AdComplete: "adComplete",
|
|
49
|
+
/**
|
|
50
|
+
* Constant defining event type for Ad skip
|
|
51
|
+
*/
|
|
52
|
+
AdSkip: "adSkip",
|
|
53
|
+
/**
|
|
54
|
+
* Constant defining event type for Chapter start
|
|
55
|
+
*/
|
|
56
|
+
ChapterStart: "chapterStart",
|
|
57
|
+
/**
|
|
58
|
+
* Constant defining event type for Chapter complete
|
|
59
|
+
*/
|
|
60
|
+
ChapterComplete: "chapterComplete",
|
|
61
|
+
/**
|
|
62
|
+
* Constant defining event type for Chapter skip
|
|
63
|
+
*/
|
|
64
|
+
ChapterSkip: "chapterSkip",
|
|
65
|
+
/**
|
|
66
|
+
* Constant defining event type for Seek start
|
|
67
|
+
*/
|
|
68
|
+
SeekStart: "seekStart",
|
|
69
|
+
/**
|
|
70
|
+
* Constant defining event type for Seek complete
|
|
71
|
+
*/
|
|
72
|
+
SeekComplete: "seekComplete",
|
|
73
|
+
/**
|
|
74
|
+
* Constant defining event type for Buffer start
|
|
75
|
+
*/
|
|
76
|
+
BufferStart: "bufferStart",
|
|
77
|
+
/**
|
|
78
|
+
* Constant defining event type for Buffer complete
|
|
79
|
+
*/
|
|
80
|
+
BufferComplete: "bufferComplete",
|
|
81
|
+
/**
|
|
82
|
+
* Constant defining event type for change in Bitrate
|
|
83
|
+
*/
|
|
84
|
+
BitrateChange: "bitrateChange",
|
|
85
|
+
/**
|
|
86
|
+
* Constant defining event type for Custom State Start
|
|
87
|
+
*/
|
|
88
|
+
StateStart: "stateStart",
|
|
89
|
+
/**
|
|
90
|
+
* Constant defining event type for Custom State End
|
|
91
|
+
*/
|
|
92
|
+
StateEnd: "stateEnd"
|
|
93
|
+
};
|
|
94
|
+
export const MEDIA_EVENTS = {
|
|
95
|
+
SessionStart: "sessionStart",
|
|
96
|
+
SessionEnd: "sessionEnd",
|
|
97
|
+
SessionComplete: "sessionComplete",
|
|
98
|
+
Play: "play",
|
|
99
|
+
Pause: "pauseStart",
|
|
100
|
+
...EVENT
|
|
101
|
+
};
|
|
102
|
+
export const MEDIA_OBJECT_KEYS = {
|
|
103
|
+
MediaResumed: "media.resumed",
|
|
104
|
+
GranularAdTracking: "media.granularadtracking"
|
|
105
|
+
};
|
|
106
|
+
export const VIDEO_METADATA_KEYS = {
|
|
107
|
+
Show: "a.media.show",
|
|
108
|
+
Season: "a.media.season",
|
|
109
|
+
Episode: "a.media.episode",
|
|
110
|
+
AssetId: "a.media.asset",
|
|
111
|
+
Genre: "a.media.genre",
|
|
112
|
+
FirstAirDate: "a.media.airDate",
|
|
113
|
+
FirstDigitalDate: "a.media.digitalDate",
|
|
114
|
+
Rating: "a.media.rating",
|
|
115
|
+
Originator: "a.media.originator",
|
|
116
|
+
Network: "a.media.network",
|
|
117
|
+
ShowType: "a.media.type",
|
|
118
|
+
AdLoad: "a.media.adLoad",
|
|
119
|
+
MVPD: "a.media.pass.mvpd",
|
|
120
|
+
Authorized: "a.media.pass.auth",
|
|
121
|
+
DayPart: "a.media.dayPart",
|
|
122
|
+
Feed: "a.media.feed",
|
|
123
|
+
StreamFormat: "a.media.format"
|
|
124
|
+
};
|
|
125
|
+
export const AUDIO_METADATA_KEYS = {
|
|
126
|
+
Artist: "a.media.artist",
|
|
127
|
+
Album: "a.media.album",
|
|
128
|
+
Label: "a.media.label",
|
|
129
|
+
Author: "a.media.author",
|
|
130
|
+
Station: "a.media.station",
|
|
131
|
+
Publisher: "a.media.publisher"
|
|
132
|
+
};
|
|
133
|
+
export const AD_METADATA_KEYS = {
|
|
134
|
+
Advertiser: "a.media.ad.advertiser",
|
|
135
|
+
CampaignId: "a.media.ad.campaign",
|
|
136
|
+
CreativeId: "a.media.ad.creative",
|
|
137
|
+
PlacementId: "a.media.ad.placement",
|
|
138
|
+
SiteId: "a.media.ad.site",
|
|
139
|
+
CreativeUrl: "a.media.ad.creativeURL"
|
|
140
|
+
};
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Copyright 2023 Adobe. All rights reserved.
|
|
3
|
+
This file is licensed to you under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
you may not use this file except in compliance with the License. You may obtain a copy
|
|
5
|
+
of the License at http://www.apache.org/licenses/LICENSE-2.0
|
|
6
|
+
|
|
7
|
+
Unless required by applicable law or agreed to in writing, software distributed under
|
|
8
|
+
the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
|
|
9
|
+
OF ANY KIND, either express or implied. See the License for the specific language
|
|
10
|
+
governing permissions and limitations under the License.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
export const mediaToXdmKeys = {
|
|
14
|
+
"a.media.show": "show",
|
|
15
|
+
"a.media.season": "season",
|
|
16
|
+
"a.media.episode": "episode",
|
|
17
|
+
"a.media.asset": "assetID",
|
|
18
|
+
"a.media.genre": "genre",
|
|
19
|
+
"a.media.airDate": "firstAirDate",
|
|
20
|
+
"a.media.digitalDate": "firstDigitalDate",
|
|
21
|
+
"a.media.rating": "rating",
|
|
22
|
+
"a.media.originator": "originator",
|
|
23
|
+
"a.media.network": "network",
|
|
24
|
+
"a.media.type": "showType",
|
|
25
|
+
"a.media.adLoad": "adLoad",
|
|
26
|
+
"a.media.pass.mvpd": "mvpd",
|
|
27
|
+
"a.media.pass.auth": "authorized",
|
|
28
|
+
"a.media.dayPart": "dayPart",
|
|
29
|
+
"a.media.feed": "feed",
|
|
30
|
+
"a.media.format": "streamFormat",
|
|
31
|
+
"a.media.artist": "artist",
|
|
32
|
+
"a.media.album": "album",
|
|
33
|
+
"a.media.label": "label",
|
|
34
|
+
"a.media.author": "author",
|
|
35
|
+
"a.media.station": "station",
|
|
36
|
+
"a.media.publisher": "publisher",
|
|
37
|
+
"media.resumed": "hasResume"
|
|
38
|
+
};
|
|
39
|
+
export const adsToXdmKeys = {
|
|
40
|
+
"a.media.ad.advertiser": "advertiser",
|
|
41
|
+
"a.media.ad.campaign": "campaignID",
|
|
42
|
+
"a.media.ad.creative": "creativeID",
|
|
43
|
+
"a.media.ad.placement": "placementID",
|
|
44
|
+
"a.media.ad.site": "siteID",
|
|
45
|
+
"a.media.ad.creativeURL": "creativeURL"
|
|
46
|
+
};
|