@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,21 @@
|
|
|
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
|
+
export default {
|
|
13
|
+
PAUSE: "media.pauseStart",
|
|
14
|
+
PLAY: "media.play",
|
|
15
|
+
BUFFERING: "media.buffering",
|
|
16
|
+
AD_START: "media.adStart",
|
|
17
|
+
SESSION_END: "media.sessionEnd",
|
|
18
|
+
SESSION_START: "media.sessionStart",
|
|
19
|
+
SESSION_COMPLETE: "media.sessionComplete",
|
|
20
|
+
PING: "media.ping"
|
|
21
|
+
};
|
|
@@ -0,0 +1,64 @@
|
|
|
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 toInteger from "../../utils/toInteger";
|
|
14
|
+
import MediaEvent from "./constants/eventTypes";
|
|
15
|
+
const ACTION = "ping";
|
|
16
|
+
const getCurrentInterval = playerSession => {
|
|
17
|
+
const currentTime = Date.now();
|
|
18
|
+
return Math.abs(currentTime - playerSession.latestTriggeredEvent) / 1000;
|
|
19
|
+
};
|
|
20
|
+
export default (({
|
|
21
|
+
config,
|
|
22
|
+
mediaEventManager,
|
|
23
|
+
mediaSessionCacheManager
|
|
24
|
+
}) => {
|
|
25
|
+
return ({
|
|
26
|
+
playerId,
|
|
27
|
+
sessionId,
|
|
28
|
+
onBeforeMediaEvent
|
|
29
|
+
}) => {
|
|
30
|
+
const {
|
|
31
|
+
mainPingInterval
|
|
32
|
+
} = config.mediaCollection;
|
|
33
|
+
const playerSession = mediaSessionCacheManager.getSession(playerId);
|
|
34
|
+
const currentInterval = getCurrentInterval(playerSession);
|
|
35
|
+
if (currentInterval > mainPingInterval) {
|
|
36
|
+
const {
|
|
37
|
+
playhead,
|
|
38
|
+
qoeDataDetails
|
|
39
|
+
} = onBeforeMediaEvent(playerId);
|
|
40
|
+
const xdm = {
|
|
41
|
+
eventType: MediaEvent.PING,
|
|
42
|
+
mediaCollection: {
|
|
43
|
+
playhead: toInteger(playhead),
|
|
44
|
+
sessionID: sessionId,
|
|
45
|
+
qoeDataDetails
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
const event = mediaEventManager.createMediaEvent({
|
|
49
|
+
options: {
|
|
50
|
+
xdm
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
return mediaEventManager.trackMediaEvent({
|
|
54
|
+
event,
|
|
55
|
+
action: ACTION
|
|
56
|
+
}).then(() => {
|
|
57
|
+
mediaSessionCacheManager.updateLastTriggeredEventTS({
|
|
58
|
+
playerId
|
|
59
|
+
});
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
return Promise.resolve();
|
|
63
|
+
};
|
|
64
|
+
});
|
|
@@ -0,0 +1,115 @@
|
|
|
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 MediaEvents from "./constants/eventTypes";
|
|
15
|
+
import createMediaRequest from "./createMediaRequest";
|
|
16
|
+
import injectTimestamp from "../Context/injectTimestamp";
|
|
17
|
+
import { toInteger } from "../../utils";
|
|
18
|
+
import { createDataCollectionRequestPayload } from "../../utils/request";
|
|
19
|
+
export default (({
|
|
20
|
+
config,
|
|
21
|
+
eventManager,
|
|
22
|
+
consent,
|
|
23
|
+
sendEdgeNetworkRequest
|
|
24
|
+
}) => {
|
|
25
|
+
return {
|
|
26
|
+
createMediaEvent({
|
|
27
|
+
options
|
|
28
|
+
}) {
|
|
29
|
+
const event = eventManager.createEvent();
|
|
30
|
+
const {
|
|
31
|
+
xdm
|
|
32
|
+
} = options;
|
|
33
|
+
const timestamp = injectTimestamp(() => new Date());
|
|
34
|
+
timestamp(xdm);
|
|
35
|
+
event.setUserXdm(xdm);
|
|
36
|
+
return event;
|
|
37
|
+
},
|
|
38
|
+
createMediaSession(options) {
|
|
39
|
+
const {
|
|
40
|
+
playerName,
|
|
41
|
+
channel,
|
|
42
|
+
version
|
|
43
|
+
} = config.mediaCollection;
|
|
44
|
+
const event = eventManager.createEvent();
|
|
45
|
+
const {
|
|
46
|
+
sessionDetails
|
|
47
|
+
} = options.xdm.mediaCollection;
|
|
48
|
+
event.setUserXdm(options.xdm);
|
|
49
|
+
event.mergeXdm({
|
|
50
|
+
eventType: MediaEvents.SESSION_START,
|
|
51
|
+
mediaCollection: {
|
|
52
|
+
sessionDetails: {
|
|
53
|
+
playerName: sessionDetails.playerName || playerName,
|
|
54
|
+
channel: sessionDetails.channel || channel,
|
|
55
|
+
appVersion: sessionDetails.appVersion || version
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
return event;
|
|
60
|
+
},
|
|
61
|
+
augmentMediaEvent({
|
|
62
|
+
event,
|
|
63
|
+
playerId,
|
|
64
|
+
onBeforeMediaEvent,
|
|
65
|
+
sessionID
|
|
66
|
+
}) {
|
|
67
|
+
if (!playerId || !onBeforeMediaEvent) {
|
|
68
|
+
return event;
|
|
69
|
+
}
|
|
70
|
+
const {
|
|
71
|
+
playhead,
|
|
72
|
+
qoeDataDetails
|
|
73
|
+
} = onBeforeMediaEvent({
|
|
74
|
+
playerId
|
|
75
|
+
});
|
|
76
|
+
event.mergeXdm({
|
|
77
|
+
mediaCollection: {
|
|
78
|
+
playhead: toInteger(playhead),
|
|
79
|
+
qoeDataDetails,
|
|
80
|
+
sessionID
|
|
81
|
+
}
|
|
82
|
+
});
|
|
83
|
+
return event;
|
|
84
|
+
},
|
|
85
|
+
trackMediaSession({
|
|
86
|
+
event,
|
|
87
|
+
playerId,
|
|
88
|
+
onBeforeMediaEvent
|
|
89
|
+
}) {
|
|
90
|
+
return eventManager.sendEvent(event, {
|
|
91
|
+
playerId,
|
|
92
|
+
onBeforeMediaEvent
|
|
93
|
+
});
|
|
94
|
+
},
|
|
95
|
+
trackMediaEvent({
|
|
96
|
+
event,
|
|
97
|
+
action
|
|
98
|
+
}) {
|
|
99
|
+
const mediaRequestPayload = createDataCollectionRequestPayload();
|
|
100
|
+
const request = createMediaRequest({
|
|
101
|
+
mediaRequestPayload,
|
|
102
|
+
action
|
|
103
|
+
});
|
|
104
|
+
mediaRequestPayload.addEvent(event);
|
|
105
|
+
event.finalize();
|
|
106
|
+
return consent.awaitConsent().then(() => {
|
|
107
|
+
return sendEdgeNetworkRequest({
|
|
108
|
+
request
|
|
109
|
+
}).then(() => {
|
|
110
|
+
return {};
|
|
111
|
+
});
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
};
|
|
115
|
+
});
|
|
@@ -0,0 +1,28 @@
|
|
|
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 { createRequest } from "../../utils/request";
|
|
14
|
+
export default (({
|
|
15
|
+
mediaRequestPayload,
|
|
16
|
+
action
|
|
17
|
+
}) => {
|
|
18
|
+
return createRequest({
|
|
19
|
+
payload: mediaRequestPayload,
|
|
20
|
+
edgeSubPath: "/va",
|
|
21
|
+
getAction() {
|
|
22
|
+
return action;
|
|
23
|
+
},
|
|
24
|
+
getUseSendBeacon() {
|
|
25
|
+
return false;
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
});
|
|
@@ -0,0 +1,63 @@
|
|
|
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 default (() => {
|
|
14
|
+
let mediaSessionCache;
|
|
15
|
+
const getSession = playerId => {
|
|
16
|
+
return mediaSessionCache[playerId] || {};
|
|
17
|
+
};
|
|
18
|
+
const saveHeartbeat = ({
|
|
19
|
+
playerId,
|
|
20
|
+
heartbeatId
|
|
21
|
+
}) => {
|
|
22
|
+
const sessionDetails = mediaSessionCache[playerId];
|
|
23
|
+
if (!sessionDetails) {
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
sessionDetails.heartbeatId = heartbeatId;
|
|
27
|
+
};
|
|
28
|
+
const stopHeartbeat = ({
|
|
29
|
+
playerId
|
|
30
|
+
}) => {
|
|
31
|
+
const sessionDetails = mediaSessionCache[playerId];
|
|
32
|
+
if (!sessionDetails) {
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
clearInterval(sessionDetails.heartbeatId);
|
|
36
|
+
sessionDetails.heartbeatId = null;
|
|
37
|
+
};
|
|
38
|
+
const updateLastTriggeredEventTS = ({
|
|
39
|
+
playerId
|
|
40
|
+
}) => {
|
|
41
|
+
const sessionDetails = mediaSessionCache[playerId];
|
|
42
|
+
if (!sessionDetails) {
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
sessionDetails.latestTriggeredEvent = Date.now();
|
|
46
|
+
};
|
|
47
|
+
const storeSession = ({
|
|
48
|
+
playerId,
|
|
49
|
+
sessionDetails
|
|
50
|
+
}) => {
|
|
51
|
+
if (mediaSessionCache === undefined) {
|
|
52
|
+
mediaSessionCache = {};
|
|
53
|
+
}
|
|
54
|
+
mediaSessionCache[playerId] = sessionDetails;
|
|
55
|
+
};
|
|
56
|
+
return {
|
|
57
|
+
getSession,
|
|
58
|
+
stopHeartbeat,
|
|
59
|
+
updateLastTriggeredEventTS,
|
|
60
|
+
storeSession,
|
|
61
|
+
saveHeartbeat
|
|
62
|
+
};
|
|
63
|
+
});
|
|
@@ -0,0 +1,30 @@
|
|
|
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 MediaEvents from "./constants/eventTypes";
|
|
14
|
+
export default (({
|
|
15
|
+
mediaSessionCacheManager
|
|
16
|
+
}) => {
|
|
17
|
+
return ({
|
|
18
|
+
playerId,
|
|
19
|
+
eventType
|
|
20
|
+
}) => {
|
|
21
|
+
if (eventType === MediaEvents.SESSION_COMPLETE || eventType === MediaEvents.SESSION_END) {
|
|
22
|
+
mediaSessionCacheManager.stopHeartbeat({
|
|
23
|
+
playerId
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
mediaSessionCacheManager.updateLastTriggeredEventTS({
|
|
27
|
+
playerId
|
|
28
|
+
});
|
|
29
|
+
};
|
|
30
|
+
});
|
|
@@ -0,0 +1,164 @@
|
|
|
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 { string, number, objectOf } from "../../utils/validation";
|
|
14
|
+
import createMediaSessionCacheManager from "./createMediaSessionCacheManager";
|
|
15
|
+
import validateMediaEventOptions from "./validateMediaEventOptions";
|
|
16
|
+
import validateSessionOptions from "./validateMediaSessionOptions";
|
|
17
|
+
import createMediaEventManager from "./createMediaEventManager";
|
|
18
|
+
import { noop } from "../../utils";
|
|
19
|
+
import createHeartbeatEngine from "./createHeartbeatEngine";
|
|
20
|
+
import createUpdateMediaSessionState from "./createUpdateMediaSessionState";
|
|
21
|
+
const createMediaCollection = ({
|
|
22
|
+
config,
|
|
23
|
+
logger,
|
|
24
|
+
eventManager,
|
|
25
|
+
sendEdgeNetworkRequest,
|
|
26
|
+
consent
|
|
27
|
+
}) => {
|
|
28
|
+
const mediaSessionCacheManager = createMediaSessionCacheManager({
|
|
29
|
+
config
|
|
30
|
+
});
|
|
31
|
+
const mediaEventManager = createMediaEventManager({
|
|
32
|
+
config,
|
|
33
|
+
eventManager,
|
|
34
|
+
logger,
|
|
35
|
+
consent,
|
|
36
|
+
sendEdgeNetworkRequest
|
|
37
|
+
});
|
|
38
|
+
const heartbeatTicker = createHeartbeatEngine({
|
|
39
|
+
config,
|
|
40
|
+
mediaEventManager,
|
|
41
|
+
mediaSessionCacheManager
|
|
42
|
+
});
|
|
43
|
+
const updateMediaSessionState = createUpdateMediaSessionState({
|
|
44
|
+
mediaSessionCacheManager
|
|
45
|
+
});
|
|
46
|
+
return {
|
|
47
|
+
lifecycle: {
|
|
48
|
+
onBeforeEvent({
|
|
49
|
+
playerId,
|
|
50
|
+
onBeforeMediaEvent,
|
|
51
|
+
onResponse = noop
|
|
52
|
+
}) {
|
|
53
|
+
onResponse(({
|
|
54
|
+
response
|
|
55
|
+
}) => {
|
|
56
|
+
const sessionId = response.getPayloadsByType("media-analytics:new-session");
|
|
57
|
+
logger.info("Media session ID returned: ", sessionId);
|
|
58
|
+
if (sessionId.length > 0) {
|
|
59
|
+
if (playerId && onBeforeMediaEvent) {
|
|
60
|
+
const heartbeatId = setInterval(() => {
|
|
61
|
+
heartbeatTicker({
|
|
62
|
+
sessionId: sessionId[0].sessionId,
|
|
63
|
+
playerId,
|
|
64
|
+
onBeforeMediaEvent
|
|
65
|
+
});
|
|
66
|
+
}, 1000);
|
|
67
|
+
mediaSessionCacheManager.saveHeartbeat({
|
|
68
|
+
playerId,
|
|
69
|
+
heartbeatId
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
return {
|
|
73
|
+
sessionId: sessionId[0].sessionId
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
return {};
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
},
|
|
80
|
+
commands: {
|
|
81
|
+
createMediaSession: {
|
|
82
|
+
optionsValidator: options => validateSessionOptions({
|
|
83
|
+
options
|
|
84
|
+
}),
|
|
85
|
+
run: options => {
|
|
86
|
+
const {
|
|
87
|
+
playerId,
|
|
88
|
+
onBeforeMediaEvent
|
|
89
|
+
} = options;
|
|
90
|
+
const event = mediaEventManager.createMediaSession(options);
|
|
91
|
+
mediaEventManager.augmentMediaEvent({
|
|
92
|
+
event,
|
|
93
|
+
playerId,
|
|
94
|
+
onBeforeMediaEvent
|
|
95
|
+
});
|
|
96
|
+
const sessionPromise = mediaEventManager.trackMediaSession({
|
|
97
|
+
event,
|
|
98
|
+
playerId,
|
|
99
|
+
onBeforeMediaEvent
|
|
100
|
+
});
|
|
101
|
+
mediaSessionCacheManager.storeSession({
|
|
102
|
+
playerId,
|
|
103
|
+
sessionDetails: {
|
|
104
|
+
sessionPromise,
|
|
105
|
+
onBeforeMediaEvent,
|
|
106
|
+
latestTriggeredEvent: Date.now()
|
|
107
|
+
}
|
|
108
|
+
});
|
|
109
|
+
return sessionPromise;
|
|
110
|
+
}
|
|
111
|
+
},
|
|
112
|
+
sendMediaEvent: {
|
|
113
|
+
optionsValidator: options => validateMediaEventOptions({
|
|
114
|
+
options
|
|
115
|
+
}),
|
|
116
|
+
run: options => {
|
|
117
|
+
const event = mediaEventManager.createMediaEvent({
|
|
118
|
+
options
|
|
119
|
+
});
|
|
120
|
+
const {
|
|
121
|
+
playerId,
|
|
122
|
+
xdm
|
|
123
|
+
} = options;
|
|
124
|
+
const eventType = xdm.eventType;
|
|
125
|
+
const action = eventType.split(".")[1];
|
|
126
|
+
const {
|
|
127
|
+
onBeforeMediaEvent,
|
|
128
|
+
sessionPromise
|
|
129
|
+
} = mediaSessionCacheManager.getSession(playerId);
|
|
130
|
+
sessionPromise.then(result => {
|
|
131
|
+
mediaEventManager.augmentMediaEvent({
|
|
132
|
+
event,
|
|
133
|
+
playerId,
|
|
134
|
+
onBeforeMediaEvent,
|
|
135
|
+
sessionID: result.sessionId
|
|
136
|
+
});
|
|
137
|
+
return mediaEventManager.trackMediaEvent({
|
|
138
|
+
event,
|
|
139
|
+
action
|
|
140
|
+
}).then(() => {
|
|
141
|
+
updateMediaSessionState({
|
|
142
|
+
playerId,
|
|
143
|
+
eventType
|
|
144
|
+
});
|
|
145
|
+
}).catch(error => {
|
|
146
|
+
logger.warn(`The Media Event of type ${action} failed.`, error);
|
|
147
|
+
});
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
};
|
|
153
|
+
};
|
|
154
|
+
createMediaCollection.namespace = "Media Collection";
|
|
155
|
+
createMediaCollection.configValidators = objectOf({
|
|
156
|
+
mediaCollection: objectOf({
|
|
157
|
+
channel: string().nonEmpty().required(),
|
|
158
|
+
playerName: string().nonEmpty().required(),
|
|
159
|
+
version: string(),
|
|
160
|
+
mainPingInterval: number().minimum(10).maximum(50).default(10),
|
|
161
|
+
adPingInterval: number().minimum(10).maximum(50).default(10)
|
|
162
|
+
}).noUnknownFields()
|
|
163
|
+
});
|
|
164
|
+
export default createMediaCollection;
|
|
@@ -0,0 +1,32 @@
|
|
|
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
|
+
import { anyOf, anything, number, objectOf, string } from "../../utils/validation";
|
|
13
|
+
export default (({
|
|
14
|
+
options
|
|
15
|
+
}) => {
|
|
16
|
+
const validator = anyOf([objectOf({
|
|
17
|
+
playerId: string().required(),
|
|
18
|
+
xdm: objectOf({
|
|
19
|
+
eventType: string().required(),
|
|
20
|
+
mediaCollection: objectOf(anything())
|
|
21
|
+
}).required()
|
|
22
|
+
}).required(), objectOf({
|
|
23
|
+
xdm: objectOf({
|
|
24
|
+
eventType: string().required(),
|
|
25
|
+
mediaCollection: objectOf({
|
|
26
|
+
playhead: number().integer().required(),
|
|
27
|
+
sessionID: string().required()
|
|
28
|
+
}).required()
|
|
29
|
+
}).required()
|
|
30
|
+
}).required()], "Error validating the sendMediaEvent command options.");
|
|
31
|
+
return validator(options);
|
|
32
|
+
});
|
|
@@ -0,0 +1,34 @@
|
|
|
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 { anyOf, anything, callback, number, objectOf, string } from "../../utils/validation";
|
|
14
|
+
export default (({
|
|
15
|
+
options
|
|
16
|
+
}) => {
|
|
17
|
+
const sessionValidator = anyOf([objectOf({
|
|
18
|
+
playerId: string().required(),
|
|
19
|
+
onBeforeMediaEvent: callback().required(),
|
|
20
|
+
xdm: objectOf({
|
|
21
|
+
mediaCollection: objectOf({
|
|
22
|
+
sessionDetails: objectOf(anything()).required()
|
|
23
|
+
})
|
|
24
|
+
})
|
|
25
|
+
}).required(), objectOf({
|
|
26
|
+
xdm: objectOf({
|
|
27
|
+
mediaCollection: objectOf({
|
|
28
|
+
playhead: number().required(),
|
|
29
|
+
sessionDetails: objectOf(anything()).required()
|
|
30
|
+
})
|
|
31
|
+
})
|
|
32
|
+
}).required()], "Error validating the createMediaSession command options.");
|
|
33
|
+
return sessionValidator(options);
|
|
34
|
+
});
|
|
@@ -32,10 +32,7 @@ export default (({
|
|
|
32
32
|
showContainers();
|
|
33
33
|
}
|
|
34
34
|
mergeQuery(event, personalizationDetails.createQueryDetails());
|
|
35
|
-
|
|
36
|
-
// This needs to be called before the response so that future sendEvent calls
|
|
37
|
-
// can know to wait until this request is complete for pending display notifications.
|
|
38
|
-
const handleNotifications = notificationHandler(personalizationDetails.isRenderDecisions(), personalizationDetails.isSendDisplayEvent(), personalizationDetails.getViewName());
|
|
35
|
+
const handleNotifications = notificationHandler(personalizationDetails.isSendDisplayEvent(), personalizationDetails.getViewName());
|
|
39
36
|
onResponse(({
|
|
40
37
|
response
|
|
41
38
|
}) => {
|
|
@@ -11,12 +11,8 @@ governing permissions and limitations under the License.
|
|
|
11
11
|
*/
|
|
12
12
|
import { defer } from "../../utils";
|
|
13
13
|
export default ((collect, renderedPropositions) => {
|
|
14
|
-
return (
|
|
15
|
-
if (!
|
|
16
|
-
// If we aren't rendering anything, then we don't need to sendDisplayEvents.
|
|
17
|
-
return () => undefined;
|
|
18
|
-
}
|
|
19
|
-
if (!isSendDisplayEvent) {
|
|
14
|
+
return (sendDisplayEvent, viewName) => {
|
|
15
|
+
if (!sendDisplayEvent) {
|
|
20
16
|
const renderedPropositionsDeferred = defer();
|
|
21
17
|
renderedPropositions.concat(renderedPropositionsDeferred.promise);
|
|
22
18
|
return renderedPropositionsDeferred.resolve;
|
|
@@ -33,7 +33,7 @@ export default (({
|
|
|
33
33
|
render,
|
|
34
34
|
returnedPropositions
|
|
35
35
|
} = processPropositions(propositionsToExecute);
|
|
36
|
-
const handleNotifications = notificationHandler(
|
|
36
|
+
const handleNotifications = notificationHandler(sendDisplayEvent, viewName);
|
|
37
37
|
render().then(handleNotifications);
|
|
38
38
|
return Promise.resolve({
|
|
39
39
|
propositions: returnedPropositions
|
|
@@ -23,7 +23,9 @@ import createEventMerge from "../components/EventMerge";
|
|
|
23
23
|
import createLibraryInfo from "../components/LibraryInfo";
|
|
24
24
|
import createDecisioningEngine from "../components/DecisioningEngine";
|
|
25
25
|
import createMachineLearning from "../components/MachineLearning";
|
|
26
|
+
import createMediaCollection from "../components/MediaCollection";
|
|
27
|
+
import createLegacyMediaAnalytics from "../components/LegacyMediaAnalytics";
|
|
26
28
|
|
|
27
29
|
// TODO: Register the Components here statically for now. They might be registered differently.
|
|
28
30
|
// TODO: Figure out how sub-components will be made available/registered
|
|
29
|
-
export default [createDataCollector, createActivityCollector, createIdentity, createAudiences, createPersonalization, createContext, createPrivacy, createEventMerge, createLibraryInfo, createMachineLearning, createDecisioningEngine];
|
|
31
|
+
export default [createDataCollector, createActivityCollector, createIdentity, createAudiences, createPersonalization, createContext, createPrivacy, createEventMerge, createLibraryInfo, createMachineLearning, createDecisioningEngine, createLegacyMediaAnalytics, createMediaCollection];
|
|
@@ -53,7 +53,7 @@ export default (({
|
|
|
53
53
|
}).then(() => {
|
|
54
54
|
const endpointDomain = request.getUseIdThirdPartyDomain() ? ID_THIRD_PARTY_DOMAIN : edgeDomain;
|
|
55
55
|
const locationHint = getLocationHint();
|
|
56
|
-
const edgeBasePathWithLocationHint = locationHint ? `${edgeBasePath}/${locationHint}` : edgeBasePath
|
|
56
|
+
const edgeBasePathWithLocationHint = locationHint ? `${edgeBasePath}/${locationHint}${request.getEdgeSubPath()}` : `${edgeBasePath}${request.getEdgeSubPath()}`;
|
|
57
57
|
const configId = request.getDatastreamIdOverride() || datastreamId;
|
|
58
58
|
const payload = request.getPayload();
|
|
59
59
|
if (configId !== datastreamId) {
|
|
@@ -0,0 +1,22 @@
|
|
|
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
|
+
export default ((fn, delay = 150) => {
|
|
13
|
+
let timer;
|
|
14
|
+
return (...args) => {
|
|
15
|
+
if (timer) {
|
|
16
|
+
clearTimeout(timer);
|
|
17
|
+
}
|
|
18
|
+
timer = setTimeout(() => {
|
|
19
|
+
fn(...args);
|
|
20
|
+
}, delay);
|
|
21
|
+
};
|
|
22
|
+
});
|
|
@@ -18,7 +18,8 @@ export default (options => {
|
|
|
18
18
|
payload,
|
|
19
19
|
getAction,
|
|
20
20
|
getUseSendBeacon,
|
|
21
|
-
datastreamIdOverride
|
|
21
|
+
datastreamIdOverride,
|
|
22
|
+
edgeSubPath
|
|
22
23
|
} = options;
|
|
23
24
|
const id = uuid();
|
|
24
25
|
let shouldUseThirdPartyDomain = false;
|
|
@@ -43,6 +44,12 @@ export default (options => {
|
|
|
43
44
|
isIdentityEstablished
|
|
44
45
|
});
|
|
45
46
|
},
|
|
47
|
+
getEdgeSubPath() {
|
|
48
|
+
if (edgeSubPath) {
|
|
49
|
+
return edgeSubPath;
|
|
50
|
+
}
|
|
51
|
+
return "";
|
|
52
|
+
},
|
|
46
53
|
getUseIdThirdPartyDomain() {
|
|
47
54
|
return shouldUseThirdPartyDomain;
|
|
48
55
|
},
|