@aws-amplify/analytics 7.0.1-console-preview.11cf989.0 → 7.0.1-console-preview.4ae78ed.0

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.
Files changed (234) hide show
  1. package/lib/errors/assertValidationError.d.ts +1 -1
  2. package/lib/errors/assertValidationError.js +7 -3
  3. package/lib/errors/validation.d.ts +3 -1
  4. package/lib/errors/validation.js +8 -0
  5. package/lib/index.d.ts +1 -1
  6. package/lib/index.js +2 -1
  7. package/lib/providers/kinesis/apis/flushEvents.d.ts +8 -0
  8. package/lib/providers/kinesis/apis/flushEvents.js +37 -0
  9. package/lib/providers/kinesis/apis/index.d.ts +1 -0
  10. package/lib/providers/kinesis/apis/index.js +3 -1
  11. package/lib/providers/kinesis/apis/record.d.ts +1 -1
  12. package/lib/providers/kinesis/apis/record.js +40 -2
  13. package/lib/providers/kinesis/index.d.ts +1 -1
  14. package/lib/providers/kinesis/index.js +2 -1
  15. package/lib/providers/kinesis/types/buffer.d.ts +15 -0
  16. package/lib/providers/kinesis/types/buffer.js +4 -0
  17. package/lib/providers/kinesis/types/index.d.ts +1 -0
  18. package/lib/providers/kinesis/types/inputs.d.ts +6 -1
  19. package/lib/providers/kinesis/utils/constants.d.ts +6 -0
  20. package/lib/providers/kinesis/utils/constants.js +11 -0
  21. package/lib/providers/kinesis/utils/getEventBuffer.d.ts +3 -0
  22. package/lib/providers/kinesis/utils/getEventBuffer.js +103 -0
  23. package/lib/providers/kinesis/utils/resolveConfig.d.ts +7 -0
  24. package/lib/providers/kinesis/utils/resolveConfig.js +24 -0
  25. package/lib/providers/kinesis-firehose/apis/flushEvents.d.ts +8 -0
  26. package/lib/providers/kinesis-firehose/apis/flushEvents.js +36 -0
  27. package/lib/providers/kinesis-firehose/apis/index.d.ts +1 -0
  28. package/lib/providers/kinesis-firehose/apis/index.js +3 -1
  29. package/lib/providers/kinesis-firehose/apis/record.d.ts +1 -1
  30. package/lib/providers/kinesis-firehose/apis/record.js +37 -2
  31. package/lib/providers/kinesis-firehose/index.d.ts +1 -1
  32. package/lib/providers/kinesis-firehose/index.js +2 -1
  33. package/lib/providers/kinesis-firehose/types/buffer.d.ts +15 -0
  34. package/lib/providers/kinesis-firehose/types/buffer.js +4 -0
  35. package/lib/providers/kinesis-firehose/types/index.d.ts +1 -0
  36. package/lib/providers/kinesis-firehose/types/inputs.d.ts +5 -1
  37. package/lib/providers/kinesis-firehose/utils/constants.d.ts +6 -0
  38. package/lib/providers/kinesis-firehose/utils/constants.js +11 -0
  39. package/lib/providers/kinesis-firehose/utils/getEventBuffer.d.ts +3 -0
  40. package/lib/providers/kinesis-firehose/utils/getEventBuffer.js +100 -0
  41. package/lib/providers/kinesis-firehose/utils/index.d.ts +2 -0
  42. package/lib/providers/kinesis-firehose/utils/index.js +9 -0
  43. package/lib/providers/kinesis-firehose/utils/resolveConfig.d.ts +7 -0
  44. package/lib/providers/kinesis-firehose/utils/resolveConfig.js +24 -0
  45. package/lib/providers/personalize/apis/flushEvents.d.ts +8 -0
  46. package/lib/providers/personalize/apis/flushEvents.js +35 -0
  47. package/lib/providers/personalize/apis/index.d.ts +1 -0
  48. package/lib/providers/personalize/apis/index.js +3 -1
  49. package/lib/providers/personalize/apis/record.d.ts +1 -1
  50. package/lib/providers/personalize/apis/record.js +65 -2
  51. package/lib/providers/personalize/index.d.ts +1 -1
  52. package/lib/providers/personalize/index.js +2 -1
  53. package/lib/providers/personalize/types/buffer.d.ts +16 -0
  54. package/lib/providers/personalize/types/buffer.js +4 -0
  55. package/lib/providers/personalize/types/index.d.ts +2 -1
  56. package/lib/providers/personalize/types/inputs.d.ts +7 -1
  57. package/lib/providers/personalize/utils/autoTrackMedia.d.ts +10 -0
  58. package/lib/providers/personalize/utils/autoTrackMedia.js +182 -0
  59. package/lib/providers/personalize/utils/cachedSession.d.ts +5 -0
  60. package/lib/providers/personalize/utils/cachedSession.js +52 -0
  61. package/lib/providers/personalize/utils/constants.d.ts +7 -0
  62. package/lib/providers/personalize/utils/constants.js +12 -0
  63. package/lib/providers/personalize/utils/getEventBuffer.d.ts +3 -0
  64. package/lib/providers/personalize/utils/getEventBuffer.js +100 -0
  65. package/lib/providers/personalize/utils/index.d.ts +5 -0
  66. package/lib/providers/personalize/utils/index.js +17 -0
  67. package/lib/providers/personalize/utils/resolveConfig.d.ts +7 -0
  68. package/lib/providers/personalize/utils/resolveConfig.js +25 -0
  69. package/lib/providers/pinpoint/apis/flushEvents.d.ts +8 -0
  70. package/lib/providers/pinpoint/apis/flushEvents.js +27 -0
  71. package/lib/providers/pinpoint/apis/identifyUser.d.ts +2 -2
  72. package/lib/providers/pinpoint/apis/identifyUser.js +3 -3
  73. package/lib/providers/pinpoint/apis/index.d.ts +1 -0
  74. package/lib/providers/pinpoint/apis/index.js +3 -1
  75. package/lib/providers/pinpoint/index.d.ts +1 -1
  76. package/lib/providers/pinpoint/index.js +2 -1
  77. package/lib/tsconfig.tsbuildinfo +1 -1
  78. package/lib/types/index.d.ts +1 -0
  79. package/lib/types/kinesis.d.ts +8 -0
  80. package/lib/types/kinesis.js +4 -0
  81. package/lib/utils/eventBuffer/EventBuffer.d.ts +16 -0
  82. package/lib/utils/eventBuffer/EventBuffer.js +91 -0
  83. package/lib/utils/eventBuffer/index.d.ts +2 -0
  84. package/lib/utils/eventBuffer/index.js +7 -0
  85. package/lib/utils/eventBuffer/types.d.ts +8 -0
  86. package/lib/utils/eventBuffer/types.js +4 -0
  87. package/lib/utils/groupBy.d.ts +1 -0
  88. package/lib/utils/groupBy.js +15 -0
  89. package/lib/utils/index.d.ts +3 -0
  90. package/lib/utils/index.js +7 -1
  91. package/lib/utils/resolveCredentials.d.ts +9 -0
  92. package/lib/utils/resolveCredentials.js +21 -0
  93. package/lib-esm/errors/assertValidationError.d.ts +1 -1
  94. package/lib-esm/errors/assertValidationError.js +7 -3
  95. package/lib-esm/errors/validation.d.ts +3 -1
  96. package/lib-esm/errors/validation.js +8 -0
  97. package/lib-esm/index.d.ts +1 -1
  98. package/lib-esm/index.js +1 -1
  99. package/lib-esm/providers/kinesis/apis/flushEvents.d.ts +8 -0
  100. package/lib-esm/providers/kinesis/apis/flushEvents.js +33 -0
  101. package/lib-esm/providers/kinesis/apis/index.d.ts +1 -0
  102. package/lib-esm/providers/kinesis/apis/index.js +1 -0
  103. package/lib-esm/providers/kinesis/apis/record.d.ts +1 -1
  104. package/lib-esm/providers/kinesis/apis/record.js +40 -2
  105. package/lib-esm/providers/kinesis/index.d.ts +1 -1
  106. package/lib-esm/providers/kinesis/index.js +1 -1
  107. package/lib-esm/providers/kinesis/types/buffer.d.ts +15 -0
  108. package/lib-esm/providers/kinesis/types/buffer.js +3 -0
  109. package/lib-esm/providers/kinesis/types/index.d.ts +1 -0
  110. package/lib-esm/providers/kinesis/types/inputs.d.ts +6 -1
  111. package/lib-esm/providers/kinesis/utils/constants.d.ts +6 -0
  112. package/lib-esm/providers/kinesis/utils/constants.js +8 -0
  113. package/lib-esm/providers/kinesis/utils/getEventBuffer.d.ts +3 -0
  114. package/lib-esm/providers/kinesis/utils/getEventBuffer.js +99 -0
  115. package/lib-esm/providers/kinesis/utils/resolveConfig.d.ts +7 -0
  116. package/lib-esm/providers/kinesis/utils/resolveConfig.js +20 -0
  117. package/lib-esm/providers/kinesis-firehose/apis/flushEvents.d.ts +8 -0
  118. package/lib-esm/providers/kinesis-firehose/apis/flushEvents.js +32 -0
  119. package/lib-esm/providers/kinesis-firehose/apis/index.d.ts +1 -0
  120. package/lib-esm/providers/kinesis-firehose/apis/index.js +1 -0
  121. package/lib-esm/providers/kinesis-firehose/apis/record.d.ts +1 -1
  122. package/lib-esm/providers/kinesis-firehose/apis/record.js +37 -2
  123. package/lib-esm/providers/kinesis-firehose/index.d.ts +1 -1
  124. package/lib-esm/providers/kinesis-firehose/index.js +1 -1
  125. package/lib-esm/providers/kinesis-firehose/types/buffer.d.ts +15 -0
  126. package/lib-esm/providers/kinesis-firehose/types/buffer.js +3 -0
  127. package/lib-esm/providers/kinesis-firehose/types/index.d.ts +1 -0
  128. package/lib-esm/providers/kinesis-firehose/types/inputs.d.ts +5 -1
  129. package/lib-esm/providers/kinesis-firehose/utils/constants.d.ts +6 -0
  130. package/lib-esm/providers/kinesis-firehose/utils/constants.js +8 -0
  131. package/lib-esm/providers/kinesis-firehose/utils/getEventBuffer.d.ts +3 -0
  132. package/lib-esm/providers/kinesis-firehose/utils/getEventBuffer.js +96 -0
  133. package/lib-esm/providers/kinesis-firehose/utils/index.d.ts +2 -0
  134. package/lib-esm/providers/kinesis-firehose/utils/index.js +4 -0
  135. package/lib-esm/providers/kinesis-firehose/utils/resolveConfig.d.ts +7 -0
  136. package/lib-esm/providers/kinesis-firehose/utils/resolveConfig.js +20 -0
  137. package/lib-esm/providers/personalize/apis/flushEvents.d.ts +8 -0
  138. package/lib-esm/providers/personalize/apis/flushEvents.js +31 -0
  139. package/lib-esm/providers/personalize/apis/index.d.ts +1 -0
  140. package/lib-esm/providers/personalize/apis/index.js +1 -0
  141. package/lib-esm/providers/personalize/apis/record.d.ts +1 -1
  142. package/lib-esm/providers/personalize/apis/record.js +65 -2
  143. package/lib-esm/providers/personalize/index.d.ts +1 -1
  144. package/lib-esm/providers/personalize/index.js +1 -1
  145. package/lib-esm/providers/personalize/types/buffer.d.ts +16 -0
  146. package/lib-esm/providers/personalize/types/buffer.js +3 -0
  147. package/lib-esm/providers/personalize/types/index.d.ts +2 -1
  148. package/lib-esm/providers/personalize/types/inputs.d.ts +7 -1
  149. package/lib-esm/providers/personalize/utils/autoTrackMedia.d.ts +10 -0
  150. package/lib-esm/providers/personalize/utils/autoTrackMedia.js +178 -0
  151. package/lib-esm/providers/personalize/utils/cachedSession.d.ts +5 -0
  152. package/lib-esm/providers/personalize/utils/cachedSession.js +47 -0
  153. package/lib-esm/providers/personalize/utils/constants.d.ts +7 -0
  154. package/lib-esm/providers/personalize/utils/constants.js +9 -0
  155. package/lib-esm/providers/personalize/utils/getEventBuffer.d.ts +3 -0
  156. package/lib-esm/providers/personalize/utils/getEventBuffer.js +96 -0
  157. package/lib-esm/providers/personalize/utils/index.d.ts +5 -0
  158. package/lib-esm/providers/personalize/utils/index.js +7 -0
  159. package/lib-esm/providers/personalize/utils/resolveConfig.d.ts +7 -0
  160. package/lib-esm/providers/personalize/utils/resolveConfig.js +21 -0
  161. package/lib-esm/providers/pinpoint/apis/flushEvents.d.ts +8 -0
  162. package/lib-esm/providers/pinpoint/apis/flushEvents.js +23 -0
  163. package/lib-esm/providers/pinpoint/apis/identifyUser.d.ts +2 -2
  164. package/lib-esm/providers/pinpoint/apis/identifyUser.js +3 -3
  165. package/lib-esm/providers/pinpoint/apis/index.d.ts +1 -0
  166. package/lib-esm/providers/pinpoint/apis/index.js +1 -0
  167. package/lib-esm/providers/pinpoint/index.d.ts +1 -1
  168. package/lib-esm/providers/pinpoint/index.js +1 -1
  169. package/lib-esm/tsconfig.tsbuildinfo +1 -1
  170. package/lib-esm/types/index.d.ts +1 -0
  171. package/lib-esm/types/kinesis.d.ts +8 -0
  172. package/lib-esm/types/kinesis.js +3 -0
  173. package/lib-esm/utils/eventBuffer/EventBuffer.d.ts +16 -0
  174. package/lib-esm/utils/eventBuffer/EventBuffer.js +88 -0
  175. package/lib-esm/utils/eventBuffer/index.d.ts +2 -0
  176. package/lib-esm/utils/eventBuffer/index.js +3 -0
  177. package/lib-esm/utils/eventBuffer/types.d.ts +8 -0
  178. package/lib-esm/utils/eventBuffer/types.js +3 -0
  179. package/lib-esm/utils/groupBy.d.ts +1 -0
  180. package/lib-esm/utils/groupBy.js +11 -0
  181. package/lib-esm/utils/index.d.ts +3 -0
  182. package/lib-esm/utils/index.js +3 -0
  183. package/lib-esm/utils/resolveCredentials.d.ts +9 -0
  184. package/lib-esm/utils/resolveCredentials.js +17 -0
  185. package/package.json +5 -4
  186. package/src/errors/assertValidationError.ts +9 -3
  187. package/src/errors/validation.ts +8 -0
  188. package/src/index.ts +1 -0
  189. package/src/providers/kinesis/apis/flushEvents.ts +42 -0
  190. package/src/providers/kinesis/apis/index.ts +1 -0
  191. package/src/providers/kinesis/apis/record.ts +54 -2
  192. package/src/providers/kinesis/index.ts +1 -1
  193. package/src/providers/kinesis/types/buffer.ts +20 -0
  194. package/src/providers/kinesis/types/index.ts +1 -0
  195. package/src/providers/kinesis/types/inputs.ts +7 -1
  196. package/src/providers/kinesis/utils/constants.ts +9 -0
  197. package/src/providers/kinesis/utils/getEventBuffer.ts +110 -0
  198. package/src/providers/kinesis/utils/resolveConfig.ts +36 -0
  199. package/src/providers/kinesis-firehose/apis/flushEvents.ts +41 -0
  200. package/src/providers/kinesis-firehose/apis/index.ts +1 -0
  201. package/src/providers/kinesis-firehose/apis/record.ts +47 -2
  202. package/src/providers/kinesis-firehose/index.ts +1 -1
  203. package/src/providers/kinesis-firehose/types/buffer.ts +20 -0
  204. package/src/providers/kinesis-firehose/types/index.ts +5 -0
  205. package/src/providers/kinesis-firehose/types/inputs.ts +6 -1
  206. package/src/providers/kinesis-firehose/utils/constants.ts +9 -0
  207. package/src/providers/kinesis-firehose/utils/getEventBuffer.ts +118 -0
  208. package/src/providers/kinesis-firehose/utils/index.ts +5 -0
  209. package/src/providers/kinesis-firehose/utils/resolveConfig.ts +36 -0
  210. package/src/providers/personalize/apis/flushEvents.ts +39 -0
  211. package/src/providers/personalize/apis/index.ts +1 -0
  212. package/src/providers/personalize/apis/record.ts +98 -2
  213. package/src/providers/personalize/index.ts +1 -1
  214. package/src/providers/personalize/types/buffer.ts +21 -0
  215. package/src/providers/personalize/types/index.ts +2 -1
  216. package/src/providers/personalize/types/inputs.ts +8 -1
  217. package/src/providers/personalize/utils/autoTrackMedia.ts +231 -0
  218. package/src/providers/personalize/utils/cachedSession.ts +67 -0
  219. package/src/providers/personalize/utils/constants.ts +12 -0
  220. package/src/providers/personalize/utils/getEventBuffer.ts +111 -0
  221. package/src/providers/personalize/utils/index.ts +11 -0
  222. package/src/providers/personalize/utils/resolveConfig.ts +41 -0
  223. package/src/providers/pinpoint/apis/flushEvents.ts +34 -0
  224. package/src/providers/pinpoint/apis/identifyUser.ts +3 -3
  225. package/src/providers/pinpoint/apis/index.ts +1 -0
  226. package/src/providers/pinpoint/index.ts +1 -1
  227. package/src/types/index.ts +2 -0
  228. package/src/types/kinesis.ts +13 -0
  229. package/src/utils/eventBuffer/EventBuffer.ts +84 -0
  230. package/src/utils/eventBuffer/index.ts +5 -0
  231. package/src/utils/eventBuffer/types.ts +12 -0
  232. package/src/utils/groupBy.ts +12 -0
  233. package/src/utils/index.ts +7 -0
  234. package/src/utils/resolveCredentials.ts +14 -0
@@ -0,0 +1,231 @@
1
+ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
+ // SPDX-License-Identifier: Apache-2.0
3
+
4
+ import { EventBuffer } from '../../../utils';
5
+ import { PersonalizeBufferEvent, PersonalizeEvent } from '../types';
6
+ import { ConsoleLogger, isBrowser } from '@aws-amplify/core/internals/utils';
7
+
8
+ enum HTML5_MEDIA_EVENT {
9
+ 'PLAY' = 'play',
10
+ 'PAUSE' = 'pause',
11
+ 'ENDED' = 'Ended',
12
+ }
13
+
14
+ enum MEDIA_TYPE {
15
+ 'IFRAME' = 'IFRAME',
16
+ 'VIDEO' = 'VIDEO',
17
+ 'AUDIO' = 'AUDIO',
18
+ }
19
+
20
+ enum EVENT_TYPE {
21
+ 'PLAY' = 'Play',
22
+ 'ENDED' = 'Ended',
23
+ 'PAUSE' = 'Pause',
24
+ 'TIME_WATCHED' = 'TimeWatched',
25
+ }
26
+
27
+ interface IRecordEvent {
28
+ (eventType: string, properties: Record<string, unknown>): void;
29
+ }
30
+
31
+ type MediaAutoTrackConfig = {
32
+ trackingId: string;
33
+ sessionId: string;
34
+ userId?: string;
35
+ event: PersonalizeEvent;
36
+ };
37
+
38
+ const logger = new ConsoleLogger('MediaAutoTrack');
39
+
40
+ const startIframeAutoTracking = (
41
+ element: HTMLElement,
42
+ recordEvent: IRecordEvent
43
+ ) => {
44
+ let isPlaying = false;
45
+ let player: any;
46
+ const mediaProperties = (): Record<string, unknown> => {
47
+ const duration = Number(parseFloat(player.getDuration()).toFixed(4));
48
+ const currentTime = Number(parseFloat(player.getCurrentTime()).toFixed(4));
49
+ return {
50
+ duration,
51
+ eventValue: Number((currentTime / duration).toFixed(4)),
52
+ };
53
+ };
54
+
55
+ const scriptElement = document.createElement('script');
56
+ scriptElement.type = 'text/javascript';
57
+ scriptElement.src = 'https://www.youtube.com/iframe_api';
58
+ document.body.append(scriptElement);
59
+
60
+ const timer = setInterval(() => {
61
+ if (isPlaying && player) {
62
+ recordEvent(EVENT_TYPE.TIME_WATCHED, mediaProperties());
63
+ }
64
+ }, 3_000);
65
+
66
+ element.addEventListener('unload', () => clearInterval(timer));
67
+
68
+ // @ts-ignore
69
+ window.onYouTubeIframeAPIReady = () => {
70
+ // @ts-ignore
71
+ delete window.onYouTubeIframeAPIReady;
72
+
73
+ // @ts-ignore
74
+ player = new window.YT.Player(element.id, {
75
+ events: {
76
+ onStateChange: (event: any) => {
77
+ const iframeEventMapping = {
78
+ 0: EVENT_TYPE.ENDED,
79
+ 1: EVENT_TYPE.PLAY,
80
+ 2: EVENT_TYPE.PAUSE,
81
+ };
82
+ // @ts-ignore
83
+ const eventType = iframeEventMapping[event.data];
84
+ switch (eventType) {
85
+ case EVENT_TYPE.ENDED:
86
+ case EVENT_TYPE.PAUSE:
87
+ isPlaying = false;
88
+ break;
89
+ case EVENT_TYPE.PLAY:
90
+ isPlaying = true;
91
+ break;
92
+ }
93
+
94
+ if (eventType) {
95
+ recordEvent(eventType, mediaProperties());
96
+ }
97
+ },
98
+ },
99
+ });
100
+ };
101
+ };
102
+
103
+ const startHTMLMediaAutoTracking = (
104
+ element: HTMLMediaElement,
105
+ recordEvent: IRecordEvent
106
+ ) => {
107
+ let isPlaying = false;
108
+ const mediaProperties = (): Record<string, unknown> => ({
109
+ duration: element.duration,
110
+ eventValue: Number((element.currentTime / element.duration).toFixed(4)),
111
+ });
112
+
113
+ const timer = setInterval(() => {
114
+ if (isPlaying) {
115
+ recordEvent(EVENT_TYPE.TIME_WATCHED, mediaProperties());
116
+ }
117
+ }, 3_000);
118
+
119
+ element.addEventListener('unload', () => clearInterval(timer));
120
+
121
+ element.addEventListener(HTML5_MEDIA_EVENT.PLAY, () => {
122
+ isPlaying = true;
123
+ recordEvent(EVENT_TYPE.PLAY, mediaProperties());
124
+ });
125
+
126
+ element.addEventListener(HTML5_MEDIA_EVENT.PAUSE, () => {
127
+ isPlaying = false;
128
+ recordEvent(EVENT_TYPE.PAUSE, mediaProperties());
129
+ });
130
+
131
+ element.addEventListener(HTML5_MEDIA_EVENT.ENDED, () => {
132
+ isPlaying = false;
133
+ recordEvent(EVENT_TYPE.ENDED, mediaProperties());
134
+ });
135
+ };
136
+
137
+ const checkElementLoaded = (interval: number, maxTries: number) => {
138
+ let retryCount = 0;
139
+ const wait = () => new Promise(r => setTimeout(r, interval));
140
+ const check = async (elementId: string): Promise<boolean> => {
141
+ if (retryCount >= maxTries) {
142
+ return false;
143
+ }
144
+
145
+ const domElement = document.getElementById(elementId);
146
+ if (domElement && domElement.clientHeight) {
147
+ return true;
148
+ } else {
149
+ retryCount += 1;
150
+ await wait();
151
+ return await check(elementId);
152
+ }
153
+ };
154
+ return check;
155
+ };
156
+
157
+ const recordEvent =
158
+ (
159
+ config: MediaAutoTrackConfig,
160
+ eventBuffer: EventBuffer<PersonalizeBufferEvent>
161
+ ): IRecordEvent =>
162
+ (eventType: string, properties: Record<string, unknown>) => {
163
+ // override eventType and merge properties
164
+ eventBuffer.append({
165
+ ...config,
166
+ event: {
167
+ ...config.event,
168
+ eventType,
169
+ properties: {
170
+ ...config.event.properties,
171
+ ...properties,
172
+ },
173
+ },
174
+ timestamp: Date.now(),
175
+ });
176
+ };
177
+
178
+ export const autoTrackMedia = async (
179
+ config: MediaAutoTrackConfig,
180
+ eventBuffer: EventBuffer<PersonalizeBufferEvent>
181
+ ) => {
182
+ const { eventType, properties } = config.event;
183
+ const { domElementId, ...otherProperties } = properties;
184
+ if (!isBrowser()) {
185
+ logger.debug(`${eventType} only for browser`);
186
+ return;
187
+ }
188
+
189
+ if (typeof domElementId === 'string' && !domElementId) {
190
+ logger.debug(
191
+ "Missing domElementId field in 'properties' for MediaAutoTrack event type."
192
+ );
193
+ return;
194
+ }
195
+
196
+ const elementId = domElementId as string;
197
+ const isElementLoaded = await checkElementLoaded(500, 5)(elementId);
198
+ if (isElementLoaded) {
199
+ const autoTrackConfigWithoutDomElementId = {
200
+ ...config,
201
+ event: {
202
+ ...config.event,
203
+ properties: otherProperties,
204
+ },
205
+ };
206
+
207
+ const element = document.getElementById(elementId);
208
+ switch (element?.tagName) {
209
+ case MEDIA_TYPE.IFRAME:
210
+ startIframeAutoTracking(
211
+ element,
212
+ recordEvent(autoTrackConfigWithoutDomElementId, eventBuffer)
213
+ );
214
+ break;
215
+ case MEDIA_TYPE.VIDEO:
216
+ case MEDIA_TYPE.AUDIO:
217
+ if (element instanceof HTMLMediaElement) {
218
+ startHTMLMediaAutoTracking(
219
+ element,
220
+ recordEvent(autoTrackConfigWithoutDomElementId, eventBuffer)
221
+ );
222
+ }
223
+ break;
224
+ default:
225
+ logger.debug(`Unsupported DOM element tag: ${element?.tagName}`);
226
+ break;
227
+ }
228
+ } else {
229
+ logger.debug('Cannot find the media element.');
230
+ }
231
+ };
@@ -0,0 +1,67 @@
1
+ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
+ // SPDX-License-Identifier: Apache-2.0
3
+
4
+ import { Cache } from '@aws-amplify/core';
5
+ import { isBrowser } from '@aws-amplify/core/internals/utils';
6
+ import { v4 as uuid } from 'uuid';
7
+
8
+ const PERSONALIZE_CACHE_USERID = '_awsct_uid';
9
+ const PERSONALIZE_CACHE_SESSIONID = '_awsct_sid';
10
+ const DEFAULT_CACHE_PREFIX = 'personalize';
11
+ const DELIMITER = '.';
12
+ const CACHE_EXPIRY_IN_DAYS = 7;
13
+
14
+ const normalize = (key: string): string =>
15
+ [key, isBrowser() ? window.location.host : DEFAULT_CACHE_PREFIX].join(
16
+ DELIMITER
17
+ );
18
+
19
+ const getCache = (key: string) => Cache.getItem(normalize(key));
20
+
21
+ const setCache = (key: string, value: unknown) => {
22
+ const expiredAt = new Date(
23
+ Date.now() + 3_600_000 * 24 * CACHE_EXPIRY_IN_DAYS
24
+ );
25
+ Cache.setItem(normalize(key), value, {
26
+ expires: expiredAt.getTime(),
27
+ });
28
+ };
29
+
30
+ export const resolveCachedSession = (trackingId: string) => {
31
+ let sessionId: string | undefined = getCache(PERSONALIZE_CACHE_SESSIONID);
32
+ if (!sessionId) {
33
+ sessionId = uuid();
34
+ setCache(PERSONALIZE_CACHE_SESSIONID, sessionId);
35
+ }
36
+
37
+ const userId: string | undefined = getCache(PERSONALIZE_CACHE_USERID);
38
+
39
+ return {
40
+ sessionId,
41
+ userId,
42
+ };
43
+ };
44
+
45
+ export const updateCachedSession = (
46
+ newUserId?: string,
47
+ currentSessionId?: string,
48
+ currentUserId?: string
49
+ ) => {
50
+ const isNoCachedSession = !currentSessionId;
51
+ const isSignOutCase = !newUserId && !currentUserId;
52
+ const isSwitchUserCase =
53
+ !!newUserId && !!currentUserId && newUserId !== currentUserId;
54
+
55
+ const isRequireNewSession =
56
+ isNoCachedSession || isSignOutCase || isSwitchUserCase;
57
+ const isRequireUpdateSession =
58
+ !!currentSessionId && !currentUserId && !!newUserId;
59
+
60
+ if (isRequireNewSession) {
61
+ const newSessionId = uuid();
62
+ setCache(PERSONALIZE_CACHE_SESSIONID, newSessionId);
63
+ setCache(PERSONALIZE_CACHE_USERID, newUserId);
64
+ } else if (isRequireUpdateSession) {
65
+ setCache(PERSONALIZE_CACHE_USERID, newUserId);
66
+ }
67
+ };
@@ -0,0 +1,12 @@
1
+ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
+ // SPDX-License-Identifier: Apache-2.0
3
+
4
+ export const DEFAULT_PERSONALIZE_CONFIG = {
5
+ flushSize: 5,
6
+ flushInterval: 5_000,
7
+ };
8
+
9
+ export const PERSONALIZE_FLUSH_SIZE_MAX = 10;
10
+
11
+ export const IDENTIFY_EVENT_TYPE = 'Identify';
12
+ export const MEDIA_AUTO_TRACK_EVENT_TYPE = 'MediaAutoTrack';
@@ -0,0 +1,111 @@
1
+ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
+ // SPDX-License-Identifier: Apache-2.0
3
+
4
+ import { EventBuffer, groupBy, IAnalyticsClient } from '../../../utils';
5
+ import { PersonalizeBufferConfig, PersonalizeBufferEvent } from '../types';
6
+ import {
7
+ PersonalizeEventsClient,
8
+ PutEventsCommand,
9
+ } from '@aws-sdk/client-personalize-events';
10
+
11
+ /**
12
+ * These Records hold cached event buffers and AWS clients.
13
+ * The hash key is determined by the region and session,
14
+ * consisting of a combined value comprising [region, sessionToken, identityId].
15
+ *
16
+ * Only one active session should exist at any given moment.
17
+ * When a new session is initiated, the previous ones should be released.
18
+ * */
19
+ const eventBufferMap: Record<string, EventBuffer<PersonalizeBufferEvent>> = {};
20
+ const cachedClients: Record<string, PersonalizeEventsClient> = {};
21
+
22
+ const DELIMITER = '#';
23
+
24
+ const createPutEventsCommand = (
25
+ ids: string,
26
+ events: PersonalizeBufferEvent[]
27
+ ): PutEventsCommand => {
28
+ const [trackingId, sessionId, userId] = ids.split(DELIMITER);
29
+ return new PutEventsCommand({
30
+ trackingId,
31
+ sessionId,
32
+ userId,
33
+ eventList: events.map(event => ({
34
+ eventId: event.event.eventId,
35
+ eventType: event.event.eventType,
36
+ properties: JSON.stringify(event.event.properties),
37
+ sentAt: new Date(event.timestamp),
38
+ })),
39
+ });
40
+ };
41
+
42
+ const submitEvents = async (
43
+ events: PersonalizeBufferEvent[],
44
+ client: PersonalizeEventsClient
45
+ ): Promise<PersonalizeBufferEvent[]> => {
46
+ const groupedByIds = Object.entries(
47
+ groupBy(
48
+ event =>
49
+ [event.trackingId, event.sessionId, event.userId]
50
+ .filter(id => !!id)
51
+ .join(DELIMITER),
52
+ events
53
+ )
54
+ );
55
+
56
+ const requests = groupedByIds
57
+ .map(([ids, events]) => createPutEventsCommand(ids, events))
58
+ .map(command => client.send(command));
59
+
60
+ await Promise.allSettled(requests);
61
+ return Promise.resolve([]);
62
+ };
63
+
64
+ export const getEventBuffer = ({
65
+ region,
66
+ flushSize,
67
+ flushInterval,
68
+ bufferSize,
69
+ credentials,
70
+ identityId,
71
+ userAgentValue,
72
+ }: PersonalizeBufferConfig): EventBuffer<PersonalizeBufferEvent> => {
73
+ const { sessionToken } = credentials;
74
+ const sessionIdentityKey = [region, sessionToken, identityId]
75
+ .filter(x => !!x)
76
+ .join('-');
77
+
78
+ if (!eventBufferMap[sessionIdentityKey]) {
79
+ const getClient = (): IAnalyticsClient<PersonalizeBufferEvent> => {
80
+ if (!cachedClients[sessionIdentityKey]) {
81
+ cachedClients[sessionIdentityKey] = new PersonalizeEventsClient({
82
+ region,
83
+ credentials,
84
+ customUserAgent: userAgentValue,
85
+ });
86
+ }
87
+ return events => submitEvents(events, cachedClients[sessionIdentityKey]);
88
+ };
89
+
90
+ eventBufferMap[sessionIdentityKey] =
91
+ new EventBuffer<PersonalizeBufferEvent>(
92
+ {
93
+ bufferSize,
94
+ flushSize,
95
+ flushInterval,
96
+ },
97
+ getClient
98
+ );
99
+
100
+ const releaseSessionKeys = Object.keys(eventBufferMap).filter(
101
+ key => key !== sessionIdentityKey
102
+ );
103
+ for (const releaseSessionKey of releaseSessionKeys) {
104
+ eventBufferMap[releaseSessionKey].release();
105
+ delete eventBufferMap[releaseSessionKey];
106
+ delete cachedClients[releaseSessionKey];
107
+ }
108
+ }
109
+
110
+ return eventBufferMap[sessionIdentityKey];
111
+ };
@@ -0,0 +1,11 @@
1
+ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
+ // SPDX-License-Identifier: Apache-2.0
3
+
4
+ export { getEventBuffer } from './getEventBuffer';
5
+ export { resolveConfig } from './resolveConfig';
6
+ export { autoTrackMedia } from './autoTrackMedia';
7
+ export { resolveCachedSession, updateCachedSession } from './cachedSession';
8
+ export {
9
+ DEFAULT_PERSONALIZE_CONFIG,
10
+ PERSONALIZE_FLUSH_SIZE_MAX,
11
+ } from './constants';
@@ -0,0 +1,41 @@
1
+ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
+ // SPDX-License-Identifier: Apache-2.0
3
+
4
+ import { Amplify } from '@aws-amplify/core';
5
+ import {
6
+ AnalyticsValidationErrorCode,
7
+ assertValidationError,
8
+ } from '../../../errors';
9
+ import { DEFAULT_PERSONALIZE_CONFIG, PERSONALIZE_FLUSH_SIZE_MAX } from './';
10
+
11
+ export const resolveConfig = () => {
12
+ const config = Amplify.getConfig().Analytics?.Personalize;
13
+ const {
14
+ region,
15
+ trackingId,
16
+ flushSize = DEFAULT_PERSONALIZE_CONFIG.flushSize,
17
+ flushInterval = DEFAULT_PERSONALIZE_CONFIG.flushInterval,
18
+ } = {
19
+ ...DEFAULT_PERSONALIZE_CONFIG,
20
+ ...config,
21
+ };
22
+
23
+ assertValidationError(!!region, AnalyticsValidationErrorCode.NoRegion);
24
+ assertValidationError(
25
+ !!trackingId,
26
+ AnalyticsValidationErrorCode.NoTrackingId
27
+ );
28
+ assertValidationError(
29
+ flushSize <= PERSONALIZE_FLUSH_SIZE_MAX,
30
+ AnalyticsValidationErrorCode.InvalidFlushSize,
31
+ `FlushSize for Personalize should be less or equal than ${PERSONALIZE_FLUSH_SIZE_MAX}`
32
+ );
33
+
34
+ return {
35
+ region,
36
+ trackingId,
37
+ bufferSize: flushSize + 1,
38
+ flushSize,
39
+ flushInterval,
40
+ };
41
+ };
@@ -0,0 +1,34 @@
1
+ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
+ // SPDX-License-Identifier: Apache-2.0
3
+
4
+ import { resolveConfig, resolveCredentials } from '../utils';
5
+ import { flushEvents as flushEventsCore } from '@aws-amplify/core/internals/providers/pinpoint';
6
+ import {
7
+ AnalyticsAction,
8
+ ConsoleLogger,
9
+ } from '@aws-amplify/core/internals/utils';
10
+ import { getAnalyticsUserAgentString } from '../../../utils';
11
+
12
+ const logger = new ConsoleLogger('Analytics');
13
+
14
+ /**
15
+ * Flushes all buffered Pinpoint events to the service.
16
+ *
17
+ * @note
18
+ * This API will make a best-effort attempt to flush events from the buffer. Events recorded immediately after invoking
19
+ * this API may not be included in the flush.
20
+ */
21
+ export const flushEvents = () => {
22
+ const { appId, region } = resolveConfig();
23
+ resolveCredentials()
24
+ .then(({ credentials, identityId }) =>
25
+ flushEventsCore(
26
+ appId,
27
+ region,
28
+ credentials,
29
+ identityId,
30
+ getAnalyticsUserAgentString(AnalyticsAction.Record)
31
+ )
32
+ )
33
+ .catch(e => logger.warn('Failed to flush events', e));
34
+ };
@@ -28,7 +28,7 @@ import { resolveConfig, resolveCredentials } from '../utils';
28
28
  * await identifyUser({
29
29
  * userId,
30
30
  * userProfile: {
31
- * email: [userEmail]
31
+ * email: 'userEmail@example.com'
32
32
  * customProperties: {
33
33
  * phoneNumber: ['555-555-5555'],
34
34
  * },
@@ -42,7 +42,7 @@ import { resolveConfig, resolveCredentials } from '../utils';
42
42
  * await identifyUser({
43
43
  * userId,
44
44
  * userProfile: {
45
- * email: [userEmail]
45
+ * email: 'userEmail@example.com'
46
46
  * customProperties: {
47
47
  * phoneNumber: ['555-555-5555'],
48
48
  * },
@@ -70,6 +70,6 @@ export const identifyUser = async ({
70
70
  userAttributes,
71
71
  userId,
72
72
  userProfile,
73
- userAgentValue: getAnalyticsUserAgentString(AnalyticsAction.UpdateEndpoint),
73
+ userAgentValue: getAnalyticsUserAgentString(AnalyticsAction.IdentifyUser),
74
74
  });
75
75
  };
@@ -3,3 +3,4 @@
3
3
 
4
4
  export { record } from './record';
5
5
  export { identifyUser } from './identifyUser';
6
+ export { flushEvents } from './flushEvents';
@@ -1,5 +1,5 @@
1
1
  // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
2
  // SPDX-License-Identifier: Apache-2.0
3
3
 
4
- export { record, identifyUser } from './apis';
4
+ export { record, identifyUser, flushEvents } from './apis';
5
5
  export { RecordInput, IdentifyUserInput } from './types/inputs';
@@ -16,3 +16,5 @@ export {
16
16
  export { AnalyticsServiceOptions } from './options';
17
17
 
18
18
  export { AnalyticsIdentifyUserInput } from './inputs';
19
+
20
+ export { KinesisStream, KinesisShard, KinesisEventData } from './kinesis';
@@ -0,0 +1,13 @@
1
+ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
+ // SPDX-License-Identifier: Apache-2.0
3
+
4
+ export type KinesisStream = {
5
+ region: string;
6
+ streamName: string;
7
+ };
8
+
9
+ export type KinesisShard = KinesisStream & {
10
+ partitionKey: string;
11
+ };
12
+
13
+ export type KinesisEventData = Record<string, unknown> | Uint8Array;
@@ -0,0 +1,84 @@
1
+ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
+ // SPDX-License-Identifier: Apache-2.0
3
+
4
+ import { ConsoleLogger } from '@aws-amplify/core/internals/utils';
5
+ import { EventBufferConfig, IAnalyticsClient } from './';
6
+
7
+ const logger = new ConsoleLogger('EventBuffer');
8
+
9
+ export class EventBuffer<T> {
10
+ private list: T[];
11
+ private readonly config: EventBufferConfig;
12
+ private getAnalyticsClient: () => IAnalyticsClient<T>;
13
+
14
+ private timer?: ReturnType<typeof setInterval>;
15
+
16
+ constructor(
17
+ config: EventBufferConfig,
18
+ getAnalyticsClient: () => IAnalyticsClient<T>
19
+ ) {
20
+ this.list = [];
21
+ this.config = config;
22
+ this.getAnalyticsClient = getAnalyticsClient;
23
+ this.startEventLoop();
24
+ }
25
+
26
+ public append(...events: T[]) {
27
+ for (const event of events) {
28
+ if (this.list.length + 1 > this.config.bufferSize) {
29
+ logger.debug(
30
+ `Exceed ${typeof event} event buffer limits, event dropped`
31
+ );
32
+ continue;
33
+ }
34
+ this.list.push(event);
35
+ }
36
+ }
37
+
38
+ public flushAll(): Promise<void> {
39
+ return this.submitEvents(this.list.length);
40
+ }
41
+
42
+ public release() {
43
+ this.list = [];
44
+ if (this.timer) {
45
+ clearInterval(this.timer);
46
+ }
47
+ }
48
+
49
+ public get length() {
50
+ return this.list.length;
51
+ }
52
+
53
+ private head(count: number) {
54
+ return this.list.splice(0, count);
55
+ }
56
+
57
+ private insertAtBeginning(...data: T[]) {
58
+ this.list.unshift(...data);
59
+ }
60
+
61
+ private startEventLoop() {
62
+ if (this.timer) {
63
+ clearInterval(this.timer);
64
+ }
65
+
66
+ const { flushSize, flushInterval } = this.config;
67
+ setInterval(() => {
68
+ this.submitEvents(flushSize);
69
+ }, flushInterval);
70
+ }
71
+
72
+ private submitEvents(count: number): Promise<void> {
73
+ const events = this.head(count);
74
+ if (events.length === 0) {
75
+ return Promise.resolve();
76
+ }
77
+
78
+ return this.getAnalyticsClient()(events).then(result => {
79
+ if (result.length > 0) {
80
+ this.insertAtBeginning(...result);
81
+ }
82
+ });
83
+ }
84
+ }
@@ -0,0 +1,5 @@
1
+ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
+ // SPDX-License-Identifier: Apache-2.0
3
+
4
+ export { EventBuffer } from './EventBuffer';
5
+ export { EventBufferConfig, IAnalyticsClient } from './types';
@@ -0,0 +1,12 @@
1
+ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
+ // SPDX-License-Identifier: Apache-2.0
3
+
4
+ export interface IAnalyticsClient<T> {
5
+ (events: T[]): Promise<T[]>;
6
+ }
7
+
8
+ export type EventBufferConfig = {
9
+ flushSize: number;
10
+ flushInterval: number;
11
+ bufferSize: number;
12
+ };
@@ -0,0 +1,12 @@
1
+ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
+ // SPDX-License-Identifier: Apache-2.0
3
+
4
+ export const groupBy = <T>(
5
+ getGroupId: (x: T) => string,
6
+ list: T[]
7
+ ): Record<string, T[]> => {
8
+ return list.reduce((result, current) => {
9
+ const groupId = getGroupId(current);
10
+ return { ...result, [groupId]: [...(result[groupId] ?? []), current] };
11
+ }, {} as Record<string, T[]>);
12
+ };