@schibsted/pulse-sdk 8.0.0-alpha.16 → 8.0.0-alpha.18

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 (398) hide show
  1. package/dist/cjs/EventBus/EventBus.js +146 -0
  2. package/dist/cjs/Tracker.js +2499 -0
  3. package/dist/cjs/Tracker.test-d.js +76 -0
  4. package/dist/cjs/app-integration.js +40 -0
  5. package/dist/cjs/builders/actor.js +60 -0
  6. package/dist/cjs/builders/consent-manager.js +134 -0
  7. package/dist/cjs/builders/consents.js +149 -0
  8. package/dist/cjs/builders/device-browser.js +89 -0
  9. package/dist/cjs/builders/device-node.js +63 -0
  10. package/dist/cjs/builders/device.js +23 -0
  11. package/dist/cjs/builders/events-anonymous-browser.js +6 -0
  12. package/dist/cjs/builders/events-anonymous-node.js +88 -0
  13. package/dist/cjs/builders/events-anonymous.js +17 -0
  14. package/dist/cjs/builders/events-browser.js +8 -0
  15. package/dist/cjs/builders/events-node.js +127 -0
  16. package/dist/cjs/builders/events.js +17 -0
  17. package/dist/cjs/builders/experimentMetadata.js +25 -0
  18. package/dist/cjs/builders/experiments.js +32 -0
  19. package/dist/cjs/builders/index.js +52 -0
  20. package/dist/cjs/builders/location.js +38 -0
  21. package/dist/cjs/builders/objects/objects-anonymous-browser.js +36 -0
  22. package/dist/cjs/builders/objects/objects-anonymous-node.js +95 -0
  23. package/dist/cjs/builders/objects/objects-anonymous.js +23 -0
  24. package/dist/cjs/builders/objects/objects-browser.js +36 -0
  25. package/dist/cjs/builders/objects/objects-node.js +126 -0
  26. package/dist/cjs/builders/objects/objects.js +23 -0
  27. package/dist/cjs/builders/objects/utils.js +23 -0
  28. package/dist/cjs/builders/origin-browser.js +28 -0
  29. package/dist/cjs/builders/origin-node.js +29 -0
  30. package/dist/cjs/builders/origin.js +23 -0
  31. package/dist/cjs/builders/provider.js +24 -0
  32. package/dist/cjs/builders/session-browser.js +97 -0
  33. package/dist/cjs/builders/session-node.js +9 -0
  34. package/dist/cjs/builders/session.js +23 -0
  35. package/dist/cjs/builders/tracker-browser.js +34 -0
  36. package/dist/cjs/builders/tracker-node.js +22 -0
  37. package/dist/cjs/builders/trackerBuilder.js +23 -0
  38. package/dist/cjs/config-browser.js +26 -0
  39. package/dist/cjs/config.js +9 -0
  40. package/dist/cjs/createPulseTracker.js +50 -0
  41. package/dist/cjs/defer.js +20 -0
  42. package/dist/cjs/getPulseTracker.js +74 -0
  43. package/dist/cjs/identity/actor.js +60 -0
  44. package/dist/cjs/identity/advertising.js +62 -0
  45. package/dist/cjs/identity/cis.js +66 -0
  46. package/dist/cjs/identity/device.js +20 -0
  47. package/dist/cjs/identity/index.js +20 -0
  48. package/dist/cjs/index.js +57 -0
  49. package/dist/cjs/leaveTracking/constants.js +26 -0
  50. package/dist/cjs/leaveTracking/index.js +368 -0
  51. package/dist/cjs/leaveTracking/types.js +19 -0
  52. package/dist/cjs/leaveTrackingTpaas/constants.js +18 -0
  53. package/dist/cjs/leaveTrackingTpaas/index.js +341 -0
  54. package/dist/cjs/leaveTrackingTpaas/types.js +19 -0
  55. package/dist/cjs/network-browser.js +35 -0
  56. package/dist/cjs/network.js +15 -0
  57. package/dist/cjs/remoteConfig/index.js +124 -0
  58. package/dist/cjs/tracker-proxy/consts.js +72 -0
  59. package/dist/cjs/tracker-proxy/proxy-provider.js +68 -0
  60. package/dist/cjs/types.js +2 -0
  61. package/dist/cjs/version.json +1 -0
  62. package/dist/cjs/visibility-observer/index.js +101 -0
  63. package/dist/cjs/warnOnce.js +11 -0
  64. package/dist/cjs/wrapper/engagement/ui-element/event-builder.js +21 -0
  65. package/dist/cjs/wrapper/engagement/ui-element/types.js +2 -0
  66. package/dist/cjs/wrapper/types/base-event.js +2 -0
  67. package/dist/cjs/wrapper/types/engagement-event.js +2 -0
  68. package/dist/cjs/wrapper/types/event.js +2 -0
  69. package/dist/cjs/wrapper/types/index.js +19 -0
  70. package/dist/cjs/wrapper/types/utils.js +2 -0
  71. package/dist/cjs/wrapper/utils/get-navigation-type.js +32 -0
  72. package/dist/cjs/wrapper/utils/page-from-page-view.js +9 -0
  73. package/dist/cjs/wrapper/view/article/event-builder.js +19 -0
  74. package/dist/cjs/wrapper/view/article/types.js +2 -0
  75. package/dist/cjs/wrapper/view/frontpage/event-builder.js +16 -0
  76. package/dist/cjs/wrapper/view/frontpage/types.js +2 -0
  77. package/dist/cjs/wrapper/view/listing/event-builder.js +14 -0
  78. package/dist/cjs/wrapper/view/listing/types.js +2 -0
  79. package/dist/cjs/wrapper/view/loginposter/event-builder.js +11 -0
  80. package/dist/cjs/wrapper/view/loginposter/types.js +2 -0
  81. package/dist/cjs/wrapper/view/page/event-builder.js +18 -0
  82. package/dist/cjs/wrapper/view/page/types.js +2 -0
  83. package/dist/cjs/wrapper/view/salesposter/event-builder.js +18 -0
  84. package/dist/cjs/wrapper/view/salesposter/types.js +2 -0
  85. package/dist/cjs/wrapper/view/ui-element/event-builder.js +15 -0
  86. package/dist/cjs/wrapper/view/ui-element/types.js +2 -0
  87. package/dist/ejs/EventBus/EventBus.js +140 -0
  88. package/dist/ejs/Tracker.js +2455 -0
  89. package/dist/ejs/Tracker.test-d.js +71 -0
  90. package/dist/ejs/app-integration.js +33 -0
  91. package/dist/ejs/builders/actor.js +53 -0
  92. package/dist/ejs/builders/consent-manager.js +125 -0
  93. package/dist/ejs/builders/consents.js +138 -0
  94. package/dist/ejs/builders/device-browser.js +69 -0
  95. package/dist/ejs/builders/device-node.js +57 -0
  96. package/dist/ejs/builders/device.js +2 -0
  97. package/dist/ejs/builders/events-anonymous-browser.js +1 -0
  98. package/dist/ejs/builders/events-anonymous-node.js +48 -0
  99. package/dist/ejs/builders/events-anonymous.js +1 -0
  100. package/dist/ejs/builders/events-browser.js +1 -0
  101. package/dist/ejs/builders/events-node.js +84 -0
  102. package/dist/ejs/builders/events.js +1 -0
  103. package/dist/ejs/builders/experimentMetadata.js +21 -0
  104. package/dist/ejs/builders/experiments.js +27 -0
  105. package/dist/ejs/builders/index.js +12 -0
  106. package/dist/ejs/builders/location.js +34 -0
  107. package/dist/ejs/builders/objects/objects-anonymous-browser.js +14 -0
  108. package/dist/ejs/builders/objects/objects-anonymous-node.js +90 -0
  109. package/dist/ejs/builders/objects/objects-anonymous.js +2 -0
  110. package/dist/ejs/builders/objects/objects-browser.js +14 -0
  111. package/dist/ejs/builders/objects/objects-node.js +121 -0
  112. package/dist/ejs/builders/objects/objects.js +2 -0
  113. package/dist/ejs/builders/objects/utils.js +20 -0
  114. package/dist/ejs/builders/origin-browser.js +6 -0
  115. package/dist/ejs/builders/origin-node.js +24 -0
  116. package/dist/ejs/builders/origin.js +2 -0
  117. package/dist/ejs/builders/provider.js +18 -0
  118. package/dist/ejs/builders/session-browser.js +90 -0
  119. package/dist/ejs/builders/session-node.js +4 -0
  120. package/dist/ejs/builders/session.js +2 -0
  121. package/dist/ejs/builders/tracker-browser.js +13 -0
  122. package/dist/ejs/builders/tracker-node.js +14 -0
  123. package/dist/ejs/builders/trackerBuilder.js +2 -0
  124. package/dist/ejs/config-browser.js +23 -0
  125. package/dist/ejs/config.js +6 -0
  126. package/dist/ejs/createPulseTracker.js +44 -0
  127. package/dist/ejs/defer.js +17 -0
  128. package/dist/ejs/getPulseTracker.js +71 -0
  129. package/dist/ejs/identity/actor.js +51 -0
  130. package/dist/ejs/identity/advertising.js +57 -0
  131. package/dist/ejs/identity/cis.js +58 -0
  132. package/dist/ejs/identity/device.js +17 -0
  133. package/dist/ejs/identity/index.js +4 -0
  134. package/dist/ejs/index.js +9 -0
  135. package/dist/ejs/leaveTracking/constants.js +19 -0
  136. package/dist/ejs/leaveTracking/index.js +319 -0
  137. package/dist/ejs/leaveTracking/types.js +16 -0
  138. package/dist/ejs/leaveTrackingTpaas/constants.js +13 -0
  139. package/dist/ejs/leaveTrackingTpaas/index.js +291 -0
  140. package/dist/ejs/leaveTrackingTpaas/types.js +16 -0
  141. package/dist/ejs/network-browser.js +32 -0
  142. package/dist/ejs/network.js +12 -0
  143. package/dist/ejs/remoteConfig/index.js +111 -0
  144. package/dist/ejs/tracker-proxy/consts.js +68 -0
  145. package/dist/ejs/tracker-proxy/proxy-provider.js +62 -0
  146. package/dist/ejs/types.js +1 -0
  147. package/dist/ejs/version.json +1 -0
  148. package/dist/ejs/visibility-observer/index.js +97 -0
  149. package/dist/ejs/warnOnce.js +9 -0
  150. package/dist/ejs/wrapper/engagement/ui-element/event-builder.js +17 -0
  151. package/dist/ejs/wrapper/engagement/ui-element/types.js +1 -0
  152. package/dist/ejs/wrapper/types/base-event.js +1 -0
  153. package/dist/ejs/wrapper/types/engagement-event.js +1 -0
  154. package/dist/ejs/wrapper/types/event.js +1 -0
  155. package/dist/ejs/wrapper/types/index.js +3 -0
  156. package/dist/ejs/wrapper/types/utils.js +1 -0
  157. package/dist/ejs/wrapper/utils/get-navigation-type.js +29 -0
  158. package/dist/ejs/wrapper/utils/page-from-page-view.js +6 -0
  159. package/dist/ejs/wrapper/view/article/event-builder.js +15 -0
  160. package/dist/ejs/wrapper/view/article/types.js +1 -0
  161. package/dist/ejs/wrapper/view/frontpage/event-builder.js +12 -0
  162. package/dist/ejs/wrapper/view/frontpage/types.js +1 -0
  163. package/dist/ejs/wrapper/view/listing/event-builder.js +10 -0
  164. package/dist/ejs/wrapper/view/listing/types.js +1 -0
  165. package/dist/ejs/wrapper/view/loginposter/event-builder.js +7 -0
  166. package/dist/ejs/wrapper/view/loginposter/types.js +1 -0
  167. package/dist/ejs/wrapper/view/page/event-builder.js +14 -0
  168. package/dist/ejs/wrapper/view/page/types.js +1 -0
  169. package/dist/ejs/wrapper/view/salesposter/event-builder.js +14 -0
  170. package/dist/ejs/wrapper/view/salesposter/types.js +1 -0
  171. package/dist/ejs/wrapper/view/ui-element/event-builder.js +11 -0
  172. package/dist/ejs/wrapper/view/ui-element/types.js +1 -0
  173. package/dist/types/EventBus/EventBus.d.ts +106 -0
  174. package/dist/types/Tracker.d.ts +1418 -0
  175. package/dist/types/Tracker.test-d.d.ts +1 -0
  176. package/dist/types/app-integration.d.ts +10 -0
  177. package/dist/types/builders/actor.d.ts +39 -0
  178. package/dist/types/builders/consent-manager.d.ts +49 -0
  179. package/dist/types/builders/consents.d.ts +107 -0
  180. package/dist/types/builders/device-browser.d.ts +6 -0
  181. package/dist/types/builders/device-node.d.ts +65 -0
  182. package/dist/types/builders/device.d.ts +2 -0
  183. package/dist/types/builders/events-anonymous-browser.d.ts +1 -0
  184. package/dist/types/builders/events-anonymous-node.d.ts +82 -0
  185. package/dist/types/builders/events-anonymous.d.ts +1 -0
  186. package/dist/types/builders/events-browser.d.ts +1 -0
  187. package/dist/types/builders/events-node.d.ts +130 -0
  188. package/dist/types/builders/events.d.ts +1 -0
  189. package/dist/types/builders/experimentMetadata.d.ts +25 -0
  190. package/dist/types/builders/experiments.d.ts +24 -0
  191. package/dist/types/builders/index.d.ts +23 -0
  192. package/dist/types/builders/location.d.ts +34 -0
  193. package/dist/types/builders/objects/objects-anonymous-browser.d.ts +11 -0
  194. package/dist/types/builders/objects/objects-anonymous-node.d.ts +52 -0
  195. package/dist/types/builders/objects/objects-anonymous.d.ts +2 -0
  196. package/dist/types/builders/objects/objects-browser.d.ts +11 -0
  197. package/dist/types/builders/objects/objects-node.d.ts +60 -0
  198. package/dist/types/builders/objects/objects.d.ts +2 -0
  199. package/dist/types/builders/objects/utils.d.ts +1 -0
  200. package/dist/types/builders/origin-browser.d.ts +5 -0
  201. package/dist/types/builders/origin-node.d.ts +18 -0
  202. package/dist/types/builders/origin.d.ts +2 -0
  203. package/dist/types/builders/provider.d.ts +14 -0
  204. package/dist/types/builders/session-browser.d.ts +20 -0
  205. package/dist/types/builders/session-node.d.ts +3 -0
  206. package/dist/types/builders/session.d.ts +2 -0
  207. package/dist/types/builders/tracker-browser.d.ts +2 -0
  208. package/dist/types/builders/tracker-node.d.ts +14 -0
  209. package/dist/types/builders/trackerBuilder.d.ts +2 -0
  210. package/dist/types/config-browser.d.ts +23 -0
  211. package/dist/types/config.d.ts +6 -0
  212. package/dist/types/createPulseTracker.d.ts +21 -0
  213. package/dist/types/defer.d.ts +28 -0
  214. package/dist/types/getPulseTracker.d.ts +59 -0
  215. package/dist/types/identity/actor.d.ts +28 -0
  216. package/dist/types/identity/advertising.d.ts +30 -0
  217. package/dist/types/identity/cis.d.ts +21 -0
  218. package/dist/types/identity/device.d.ts +12 -0
  219. package/dist/types/identity/index.d.ts +4 -0
  220. package/dist/types/index.d.ts +31 -0
  221. package/dist/types/leaveTracking/constants.d.ts +26 -0
  222. package/dist/types/leaveTracking/index.d.ts +23 -0
  223. package/dist/types/leaveTracking/types.d.ts +78 -0
  224. package/dist/types/leaveTrackingTpaas/constants.d.ts +13 -0
  225. package/dist/types/leaveTrackingTpaas/index.d.ts +28 -0
  226. package/dist/types/leaveTrackingTpaas/types.d.ts +45 -0
  227. package/dist/types/network-browser.d.ts +5 -0
  228. package/dist/types/network.d.ts +4 -0
  229. package/dist/types/remoteConfig/index.d.ts +32 -0
  230. package/dist/types/tracker-proxy/consts.d.ts +45 -0
  231. package/dist/types/tracker-proxy/proxy-provider.d.ts +2 -0
  232. package/dist/types/types.d.ts +93 -0
  233. package/dist/types/visibility-observer/index.d.ts +38 -0
  234. package/dist/types/warnOnce.d.ts +2 -0
  235. package/dist/types/wrapper/engagement/ui-element/event-builder.d.ts +3 -0
  236. package/dist/types/wrapper/engagement/ui-element/types.d.ts +29 -0
  237. package/dist/types/wrapper/types/base-event.d.ts +74 -0
  238. package/dist/types/wrapper/types/engagement-event.d.ts +5 -0
  239. package/dist/types/wrapper/types/event.d.ts +41 -0
  240. package/dist/types/wrapper/types/index.d.ts +3 -0
  241. package/dist/types/wrapper/types/utils.d.ts +5 -0
  242. package/dist/types/wrapper/utils/get-navigation-type.d.ts +3 -0
  243. package/dist/types/wrapper/utils/page-from-page-view.d.ts +3 -0
  244. package/dist/types/wrapper/view/article/event-builder.d.ts +2 -0
  245. package/dist/types/wrapper/view/article/types.d.ts +27 -0
  246. package/dist/types/wrapper/view/frontpage/event-builder.d.ts +2 -0
  247. package/dist/types/wrapper/view/frontpage/types.d.ts +18 -0
  248. package/dist/types/wrapper/view/listing/event-builder.d.ts +2 -0
  249. package/dist/types/wrapper/view/listing/types.d.ts +27 -0
  250. package/dist/types/wrapper/view/loginposter/event-builder.d.ts +2 -0
  251. package/dist/types/wrapper/view/loginposter/types.d.ts +14 -0
  252. package/dist/types/wrapper/view/page/event-builder.d.ts +2 -0
  253. package/dist/types/wrapper/view/page/types.d.ts +16 -0
  254. package/dist/types/wrapper/view/salesposter/event-builder.d.ts +2 -0
  255. package/dist/types/wrapper/view/salesposter/types.d.ts +15 -0
  256. package/dist/types/wrapper/view/ui-element/event-builder.d.ts +3 -0
  257. package/dist/types/wrapper/view/ui-element/types.d.ts +28 -0
  258. package/node_modules/@schibsted/pulse-cis-sync/dist/cjs/cis-browser.d.ts +26 -0
  259. package/node_modules/@schibsted/pulse-cis-sync/dist/cjs/cis-browser.js +273 -0
  260. package/node_modules/@schibsted/pulse-cis-sync/dist/cjs/cis-browser.js.map +1 -0
  261. package/node_modules/@schibsted/pulse-cis-sync/dist/cjs/cis.d.ts +10 -0
  262. package/node_modules/@schibsted/pulse-cis-sync/dist/cjs/cis.js +7 -0
  263. package/node_modules/@schibsted/pulse-cis-sync/dist/cjs/cis.js.map +1 -0
  264. package/node_modules/@schibsted/pulse-cis-sync/dist/cjs/eventEmitter.d.ts +14 -0
  265. package/node_modules/@schibsted/pulse-cis-sync/dist/cjs/eventEmitter.js +39 -0
  266. package/node_modules/@schibsted/pulse-cis-sync/dist/cjs/eventEmitter.js.map +1 -0
  267. package/node_modules/@schibsted/pulse-cis-sync/dist/cjs/index.d.ts +4 -0
  268. package/node_modules/@schibsted/pulse-cis-sync/dist/cjs/index.js +12 -0
  269. package/node_modules/@schibsted/pulse-cis-sync/dist/cjs/index.js.map +1 -0
  270. package/node_modules/@schibsted/pulse-cis-sync/dist/cjs/pulse-cookie.d.ts +55 -0
  271. package/node_modules/@schibsted/pulse-cis-sync/dist/cjs/pulse-cookie.js +276 -0
  272. package/node_modules/@schibsted/pulse-cis-sync/dist/cjs/pulse-cookie.js.map +1 -0
  273. package/node_modules/@schibsted/pulse-cis-sync/dist/cjs/storage/pulseStorage.d.ts +36 -0
  274. package/node_modules/@schibsted/pulse-cis-sync/dist/cjs/storage/pulseStorage.js +87 -0
  275. package/node_modules/@schibsted/pulse-cis-sync/dist/cjs/storage/pulseStorage.js.map +1 -0
  276. package/node_modules/@schibsted/pulse-cis-sync/dist/cjs/storage/storage.d.ts +6 -0
  277. package/node_modules/@schibsted/pulse-cis-sync/dist/cjs/storage/storage.js +21 -0
  278. package/node_modules/@schibsted/pulse-cis-sync/dist/cjs/storage/storage.js.map +1 -0
  279. package/node_modules/@schibsted/pulse-cis-sync/dist/cjs/types.d.ts +24 -0
  280. package/node_modules/@schibsted/pulse-cis-sync/dist/cjs/types.js +3 -0
  281. package/node_modules/@schibsted/pulse-cis-sync/dist/cjs/types.js.map +1 -0
  282. package/node_modules/@schibsted/pulse-cis-sync/dist/ejs/cis-browser.d.ts +26 -0
  283. package/node_modules/@schibsted/pulse-cis-sync/dist/ejs/cis-browser.js +203 -0
  284. package/node_modules/@schibsted/pulse-cis-sync/dist/ejs/cis-browser.js.map +1 -0
  285. package/node_modules/@schibsted/pulse-cis-sync/dist/ejs/cis.d.ts +10 -0
  286. package/node_modules/@schibsted/pulse-cis-sync/dist/ejs/cis.js +4 -0
  287. package/node_modules/@schibsted/pulse-cis-sync/dist/ejs/cis.js.map +1 -0
  288. package/node_modules/@schibsted/pulse-cis-sync/dist/ejs/eventEmitter.d.ts +14 -0
  289. package/node_modules/@schibsted/pulse-cis-sync/dist/ejs/eventEmitter.js +35 -0
  290. package/node_modules/@schibsted/pulse-cis-sync/dist/ejs/eventEmitter.js.map +1 -0
  291. package/node_modules/@schibsted/pulse-cis-sync/dist/ejs/index.d.ts +4 -0
  292. package/node_modules/@schibsted/pulse-cis-sync/dist/ejs/index.js +3 -0
  293. package/node_modules/@schibsted/pulse-cis-sync/dist/ejs/index.js.map +1 -0
  294. package/node_modules/@schibsted/pulse-cis-sync/dist/ejs/pulse-cookie.d.ts +55 -0
  295. package/node_modules/@schibsted/pulse-cis-sync/dist/ejs/pulse-cookie.js +254 -0
  296. package/node_modules/@schibsted/pulse-cis-sync/dist/ejs/pulse-cookie.js.map +1 -0
  297. package/node_modules/@schibsted/pulse-cis-sync/dist/ejs/storage/pulseStorage.d.ts +36 -0
  298. package/node_modules/@schibsted/pulse-cis-sync/dist/ejs/storage/pulseStorage.js +50 -0
  299. package/node_modules/@schibsted/pulse-cis-sync/dist/ejs/storage/pulseStorage.js.map +1 -0
  300. package/node_modules/@schibsted/pulse-cis-sync/dist/ejs/storage/storage.d.ts +6 -0
  301. package/node_modules/@schibsted/pulse-cis-sync/dist/ejs/storage/storage.js +17 -0
  302. package/node_modules/@schibsted/pulse-cis-sync/dist/ejs/storage/storage.js.map +1 -0
  303. package/node_modules/@schibsted/pulse-cis-sync/dist/ejs/types.d.ts +24 -0
  304. package/node_modules/@schibsted/pulse-cis-sync/dist/ejs/types.js +2 -0
  305. package/node_modules/@schibsted/pulse-cis-sync/dist/ejs/types.js.map +1 -0
  306. package/node_modules/@schibsted/pulse-cis-sync/dist/types/cis-browser.d.ts +26 -0
  307. package/node_modules/@schibsted/pulse-cis-sync/dist/types/cis.d.ts +10 -0
  308. package/node_modules/@schibsted/pulse-cis-sync/dist/types/eventEmitter.d.ts +14 -0
  309. package/node_modules/@schibsted/pulse-cis-sync/dist/types/index.d.ts +4 -0
  310. package/node_modules/@schibsted/pulse-cis-sync/dist/types/pulse-cookie.d.ts +55 -0
  311. package/node_modules/@schibsted/pulse-cis-sync/dist/types/storage/pulseStorage.d.ts +36 -0
  312. package/node_modules/@schibsted/pulse-cis-sync/dist/types/storage/storage.d.ts +6 -0
  313. package/node_modules/@schibsted/pulse-cis-sync/dist/types/types.d.ts +24 -0
  314. package/node_modules/@schibsted/pulse-cis-sync/package.json +44 -0
  315. package/node_modules/@schibsted/pulse-utils/dist/cjs/cookie-config.js +10 -0
  316. package/node_modules/@schibsted/pulse-utils/dist/cjs/cookie.js +86 -0
  317. package/node_modules/@schibsted/pulse-utils/dist/cjs/events.js +109 -0
  318. package/node_modules/@schibsted/pulse-utils/dist/cjs/get.js +18 -0
  319. package/node_modules/@schibsted/pulse-utils/dist/cjs/getRootDomain.js +54 -0
  320. package/node_modules/@schibsted/pulse-utils/dist/cjs/index.js +38 -0
  321. package/node_modules/@schibsted/pulse-utils/dist/cjs/merge.js +38 -0
  322. package/node_modules/@schibsted/pulse-utils/dist/cjs/objects.js +34 -0
  323. package/node_modules/@schibsted/pulse-utils/dist/cjs/omit.js +9 -0
  324. package/node_modules/@schibsted/pulse-utils/dist/cjs/randomString.js +18 -0
  325. package/node_modules/@schibsted/pulse-utils/dist/cjs/throttle.js +34 -0
  326. package/node_modules/@schibsted/pulse-utils/dist/cjs/webApi.js +21 -0
  327. package/node_modules/@schibsted/pulse-utils/dist/ejs/cookie-config.js +7 -0
  328. package/node_modules/@schibsted/pulse-utils/dist/ejs/cookie.js +81 -0
  329. package/node_modules/@schibsted/pulse-utils/dist/ejs/events.js +103 -0
  330. package/node_modules/@schibsted/pulse-utils/dist/ejs/get.js +15 -0
  331. package/node_modules/@schibsted/pulse-utils/dist/ejs/getRootDomain.js +49 -0
  332. package/node_modules/@schibsted/pulse-utils/dist/ejs/index.js +11 -0
  333. package/node_modules/@schibsted/pulse-utils/dist/ejs/merge.js +35 -0
  334. package/node_modules/@schibsted/pulse-utils/dist/ejs/objects.js +26 -0
  335. package/node_modules/@schibsted/pulse-utils/dist/ejs/omit.js +6 -0
  336. package/node_modules/@schibsted/pulse-utils/dist/ejs/randomString.js +15 -0
  337. package/node_modules/@schibsted/pulse-utils/dist/ejs/throttle.js +31 -0
  338. package/node_modules/@schibsted/pulse-utils/dist/ejs/webApi.js +17 -0
  339. package/node_modules/@schibsted/pulse-utils/dist/types/cookie-config.d.ts +7 -0
  340. package/node_modules/@schibsted/pulse-utils/dist/types/cookie.d.ts +23 -0
  341. package/node_modules/@schibsted/pulse-utils/dist/types/events.d.ts +17 -0
  342. package/node_modules/@schibsted/pulse-utils/dist/types/get.d.ts +1 -0
  343. package/node_modules/@schibsted/pulse-utils/dist/types/getRootDomain.d.ts +13 -0
  344. package/node_modules/@schibsted/pulse-utils/dist/types/index.d.ts +11 -0
  345. package/node_modules/@schibsted/pulse-utils/dist/types/merge.d.ts +4 -0
  346. package/node_modules/@schibsted/pulse-utils/dist/types/objects.d.ts +6 -0
  347. package/node_modules/@schibsted/pulse-utils/dist/types/omit.d.ts +3 -0
  348. package/node_modules/@schibsted/pulse-utils/dist/types/randomString.d.ts +1 -0
  349. package/node_modules/@schibsted/pulse-utils/dist/types/throttle.d.ts +3 -0
  350. package/node_modules/@schibsted/pulse-utils/dist/types/webApi.d.ts +10 -0
  351. package/node_modules/@schibsted/pulse-utils/package.json +36 -0
  352. package/node_modules/@schibsted/tpaas-event-builder/dist/cjs/builders/anonymous.js +8 -0
  353. package/node_modules/@schibsted/tpaas-event-builder/dist/cjs/builders/baseEvent.js +9 -0
  354. package/node_modules/@schibsted/tpaas-event-builder/dist/cjs/builders/consents.js +15 -0
  355. package/node_modules/@schibsted/tpaas-event-builder/dist/cjs/builders/device.js +211 -0
  356. package/node_modules/@schibsted/tpaas-event-builder/dist/cjs/builders/experiments.js +11 -0
  357. package/node_modules/@schibsted/tpaas-event-builder/dist/cjs/builders/navigationType.js +52 -0
  358. package/node_modules/@schibsted/tpaas-event-builder/dist/cjs/builders/pageInfo.js +24 -0
  359. package/node_modules/@schibsted/tpaas-event-builder/dist/cjs/builders/pageviewId.js +11 -0
  360. package/node_modules/@schibsted/tpaas-event-builder/dist/cjs/builders/provider.js +12 -0
  361. package/node_modules/@schibsted/tpaas-event-builder/dist/cjs/builders/referrer.js +19 -0
  362. package/node_modules/@schibsted/tpaas-event-builder/dist/cjs/builders/session.js +114 -0
  363. package/node_modules/@schibsted/tpaas-event-builder/dist/cjs/builders/time.js +15 -0
  364. package/node_modules/@schibsted/tpaas-event-builder/dist/cjs/builders/trackerBuilder.js +15 -0
  365. package/node_modules/@schibsted/tpaas-event-builder/dist/cjs/builders/user.js +26 -0
  366. package/node_modules/@schibsted/tpaas-event-builder/dist/cjs/builders/utm.js +35 -0
  367. package/node_modules/@schibsted/tpaas-event-builder/dist/cjs/builders.js +264 -0
  368. package/node_modules/@schibsted/tpaas-event-builder/dist/cjs/index.js +17 -0
  369. package/node_modules/@schibsted/tpaas-event-builder/dist/cjs/types.js +2 -0
  370. package/node_modules/@schibsted/tpaas-event-builder/dist/ejs/builders/anonymous.js +5 -0
  371. package/node_modules/@schibsted/tpaas-event-builder/dist/ejs/builders/baseEvent.js +6 -0
  372. package/node_modules/@schibsted/tpaas-event-builder/dist/ejs/builders/consents.js +12 -0
  373. package/node_modules/@schibsted/tpaas-event-builder/dist/ejs/builders/device.js +174 -0
  374. package/node_modules/@schibsted/tpaas-event-builder/dist/ejs/builders/experiments.js +7 -0
  375. package/node_modules/@schibsted/tpaas-event-builder/dist/ejs/builders/navigationType.js +48 -0
  376. package/node_modules/@schibsted/tpaas-event-builder/dist/ejs/builders/pageInfo.js +20 -0
  377. package/node_modules/@schibsted/tpaas-event-builder/dist/ejs/builders/pageviewId.js +7 -0
  378. package/node_modules/@schibsted/tpaas-event-builder/dist/ejs/builders/provider.js +9 -0
  379. package/node_modules/@schibsted/tpaas-event-builder/dist/ejs/builders/referrer.js +15 -0
  380. package/node_modules/@schibsted/tpaas-event-builder/dist/ejs/builders/session.js +108 -0
  381. package/node_modules/@schibsted/tpaas-event-builder/dist/ejs/builders/time.js +11 -0
  382. package/node_modules/@schibsted/tpaas-event-builder/dist/ejs/builders/trackerBuilder.js +11 -0
  383. package/node_modules/@schibsted/tpaas-event-builder/dist/ejs/builders/user.js +22 -0
  384. package/node_modules/@schibsted/tpaas-event-builder/dist/ejs/builders/utm.js +31 -0
  385. package/node_modules/@schibsted/tpaas-event-builder/dist/ejs/builders.js +209 -0
  386. package/node_modules/@schibsted/tpaas-event-builder/dist/ejs/index.js +1 -0
  387. package/node_modules/@schibsted/tpaas-event-builder/dist/ejs/types.js +1 -0
  388. package/node_modules/@schibsted/tpaas-event-builder/dist/index.d.ts +5171 -0
  389. package/node_modules/@schibsted/tpaas-event-builder/package.json +40 -0
  390. package/node_modules/@schibsted/tpaas-schemas/dist/cjs/constants.js +62 -1
  391. package/node_modules/@schibsted/tpaas-schemas/dist/ejs/constants.js +61 -0
  392. package/node_modules/@schibsted/tpaas-schemas/dist/index.d.ts +128 -0
  393. package/package.json +58 -13
  394. package/CHANGELOG.md +0 -1035
  395. package/dist/index.d.ts +0 -13
  396. package/dist/index.d.ts.map +0 -1
  397. package/dist/index.js +0 -47
  398. package/dist/index.js.map +0 -1
@@ -0,0 +1,2455 @@
1
+ import { parsePulseCookies } from '@schibsted/pulse-cis-sync';
2
+ import { evaluateAndFlatten, isBrowser, isFunction, isPromise, isString, pulseMerge, throttle, } from '@schibsted/pulse-utils';
3
+ import { buildAnonymousViewUIElementEvent, buildCompletedHealthActionEvent, buildEngagementAudioEvent, buildEngagementFormEvent, buildEngagementHealthUIElementEvent, buildEngagementOfferEvent, buildEngagementTeaserEvent, buildEngagementUIElementEvent, buildEngagementVideoAdEvent, buildEngagementVideoEvent, buildEngagementWidgetEvent, buildImpressionAdSlotEvent, buildImpressionFormEvent, buildImpressionHealthUIElementEvent, buildImpressionOfferEvent, buildImpressionPlayerEvent, buildImpressionTeaserEvent, buildImpressionUIElementEvent, buildImpressionWidgetEvent, buildLeaveArticleEvent, buildLeaveAudioPageEvent, buildLeaveErrorEvent, buildLeaveFrontpageEvent, buildLeaveLandingpageEvent, buildLeaveListingEvent, buildLeaveLockedArticleEvent, buildLeaveLockedAudioEvent, buildLeaveLockedAudioPageEvent, buildLeaveLockedVideoEvent, buildLeaveLockedVideoPageEvent, buildLeavePageEvent, buildLeaveVideoPageEvent, buildLeaveWeatherEvent, buildViewArticleEvent, buildViewAudioEvent, buildViewAudioPageEvent, buildViewErrorEvent, buildViewFrontpageEvent, buildViewHealthPageEvent, buildViewLandingpageEvent, buildViewListingEvent, buildViewLockedArticleEvent, buildViewLockedAudioEvent, buildViewLockedAudioPageEvent, buildViewLockedVideoEvent, buildViewLockedVideoPageEvent, buildViewPageEvent, buildViewTitleEvent, buildViewVideoEvent, buildViewVideoPageEvent, buildViewWeatherEvent, getCommonBuildersOutput, } from '@schibsted/tpaas-event-builder';
4
+ import { LeaveArticle, LeaveAudioPage, LeaveError, LeaveFrontpage, LeaveLandingpage, LeaveListing, LeaveLockedArticle, LeaveLockedAudioPage, LeaveLockedVideoPage, LeavePage, LeaveVideoPage, LeaveWeather, ViewArticle, ViewError, ViewFrontpage, ViewListing, ViewLockedArticle, ViewLockedVideo, ViewPage, ViewTitle, } from '@schibsted/tpaas-schemas';
5
+ import logger from 'loglevel';
6
+ import { v4 } from 'uuid';
7
+ import { getDefaultAltHandler, getDefaultNativeJwe } from './app-integration';
8
+ import { provider, session as sessionBuilder } from './builders';
9
+ import { getConsentsWaitForAnalytics, getFallbackConsents } from './builders/consent-manager';
10
+ import { applyAdvertisingConsent, applyAdvertisingConsentSync, } from './builders/consents';
11
+ import { engagementEvent, identityEvent, routableEvent, trackerEvent } from './builders/events';
12
+ import { anonymousEngagementEvent, anonymousTrackerEvent } from './builders/events-anonymous-node';
13
+ import { readSession } from './builders/session-browser';
14
+ import { baseConfig as defaultConfig } from './config';
15
+ import { CISEndpoints, collectorEndpoints, remoteConfig } from './config-browser';
16
+ import defer from './defer';
17
+ import { createEventBus } from './EventBus/EventBus';
18
+ import * as identity from './identity';
19
+ import { addPageLeaveTracking, leaveTrackingIsActive, removePageLeaveTracking, resetViewedContent, trackActivePageLeave, trackPageLeave, updatePageLeaveEvent, updatePageLeaveTracking, updateViewedContent, } from './leaveTracking';
20
+ import { addTpaasLeaveTracking, getTpaasLeaveObject, leaveTpaasTrackingIsActive, resetTpaasViewedContent, shouldEnableLeaveTracking, trackTpaasActiveLeave, updateTpaasLeaveTracking, updateTpaasViewedContent, } from './leaveTrackingTpaas';
21
+ import send from './network';
22
+ import * as config from './remoteConfig';
23
+ import { startProxyProviderListener } from './tracker-proxy/proxy-provider';
24
+ import version from './version.json';
25
+ import { VisibilityObserver } from './visibility-observer';
26
+ import warnOnce from './warnOnce';
27
+ import { buildClickUIElementEvent } from './wrapper/engagement/ui-element/event-builder';
28
+ import { pageFromPageView } from './wrapper/utils/page-from-page-view';
29
+ import { buildLegacyViewArticleEvent } from './wrapper/view/article/event-builder';
30
+ import { buildLegacyViewFrontpageEvent } from './wrapper/view/frontpage/event-builder';
31
+ import { buildLegacyViewListingEvent } from './wrapper/view/listing/event-builder';
32
+ import { buildViewLoginPosterEvent } from './wrapper/view/loginposter/event-builder';
33
+ import { buildLegacyViewPageEvent } from './wrapper/view/page/event-builder';
34
+ import { buildViewSalesPosterEvent } from './wrapper/view/salesposter/event-builder';
35
+ import { buildLegacyViewUIElementEvent } from './wrapper/view/ui-element/event-builder';
36
+ const { generateProviderSDRN: providerSdrn } = provider;
37
+ /**
38
+ * Event Builder lookup
39
+ * @internal
40
+ */
41
+ const events = {
42
+ identity: identityEvent,
43
+ trackerEvent: trackerEvent,
44
+ engagementEvent: engagementEvent,
45
+ routableEvent: routableEvent,
46
+ };
47
+ /**
48
+ * @typeParam T Type of event to track
49
+ * @param name
50
+ * @internal
51
+ */
52
+ function getEventBuilder(name) {
53
+ return name in events ? events[name] : events.trackerEvent;
54
+ }
55
+ /**
56
+ * Event Builder lookup for anonymous events
57
+ * @internal
58
+ */
59
+ const anonymousEvents = {
60
+ trackerEvent: anonymousTrackerEvent,
61
+ engagementEvent: anonymousEngagementEvent,
62
+ };
63
+ /**
64
+ * @typeParam T Type of event to track
65
+ * @param name
66
+ * @internal
67
+ */
68
+ function getAnonymousEventBuilder(name) {
69
+ return name in anonymousEvents ? anonymousEvents[name] : anonymousEvents.trackerEvent;
70
+ }
71
+ /**
72
+ * Determines if the SDK is running in a Hybrid (WebView) environment.
73
+ *
74
+ * @remarks
75
+ *
76
+ * Historically, we have detected the presence of "nativeJwe" config coming from the native app to flag that setup.
77
+ * Additionally, a config param can be passed to explicitly indicate that the tracker was initialised in a mobile WebView.
78
+ *
79
+ * @param config {SDKConfigInput}
80
+ * @internal
81
+ */
82
+ const isHybrid = (config) => Boolean(config?.isHybrid) || Boolean(config?.nativeJwe);
83
+ /**
84
+ * @internal
85
+ * Used to register whether the Collector and CIS base urls are set in the config params, before the state is populated
86
+ * with the default values.
87
+ */
88
+ let isCollectorInConfig = false;
89
+ let isCisInConfig = false;
90
+ /**
91
+ * @internal
92
+ */
93
+ export const BookmarkKeys = {
94
+ PAGE_VIEW: 'page-view',
95
+ };
96
+ const eventBus = createEventBus({
97
+ namespace: 'pulse',
98
+ domBridge: true,
99
+ preventBridgeEcho: true,
100
+ });
101
+ export function subscribe(eventName, callback) {
102
+ return eventBus.on(eventName, callback);
103
+ }
104
+ export function subscribeOnce(eventName, callback) {
105
+ return eventBus.once(eventName, callback);
106
+ }
107
+ export function subscribeWithState(eventName, callback) {
108
+ return eventBus.onWithState(eventName, callback);
109
+ }
110
+ export function unsubscribe(eventName, callback) {
111
+ eventBus.off(eventName, callback);
112
+ }
113
+ /**
114
+ * @class Tracker
115
+ */
116
+ export default class Tracker {
117
+ /**
118
+ * > [!WARNING]
119
+ * >
120
+ * > For legacy reasons the `providerId` parameter is called so, but it is actually the
121
+ * > `CLIENT-ID` of the site or app.
122
+ * > Do not mix it up with a full `SDRN` Provider ID. Ex:<br/>
123
+ * > * `PROVIDER-ID` = `sdrn:schibsted:client:my-client-id`<br/>
124
+ * > * `CLIENT-ID` = `my-client-id` = `config.providerId`
125
+ *
126
+ * @param providerId `CLIENT-ID` of the site or app.
127
+ * @param config Options to set the SDK with
128
+ * @param builders Initial values for event properties that will be persisted across events
129
+ */
130
+ constructor(providerId, config, builders) {
131
+ // we have separated observers for legacy and tpaas events in order to allow
132
+ // the tracking of the same element with both old and new events at the same time
133
+ this.legacyVisibilityObservers = new Map();
134
+ this.visibilityObservers = new Map();
135
+ this.legacyCurrentPage = {
136
+ id: 'undefined-id',
137
+ type: 'Page',
138
+ url: typeof window !== 'undefined' ? window.location.href : '',
139
+ };
140
+ this.currentPage = undefined;
141
+ /**
142
+ * Promise that resolves when a session ID becomes available
143
+ * @private
144
+ */
145
+ this.sessionIdPromise = null;
146
+ this.setPageDefaults = (pageViewEvent) => {
147
+ this.legacyCurrentPage = pageFromPageView(pageViewEvent);
148
+ if (pageViewEvent.origin) {
149
+ const pageDefaults = { origin: pageViewEvent.origin };
150
+ this.update(pageDefaults, true);
151
+ }
152
+ };
153
+ this.setCurrentPage = (id, type) => {
154
+ this.currentPage = {
155
+ pageId: id,
156
+ pageType: type,
157
+ url: isBrowser ? window.location.href : undefined,
158
+ };
159
+ };
160
+ logger.setLevel(config?.logLevel ?? logger.levels.ERROR);
161
+ // runtime check for providerId inconsistency
162
+ if (!providerId || !(typeof providerId === 'string')) {
163
+ throw new Error('Required parameter `providerId` missing');
164
+ }
165
+ let includeAdvertising;
166
+ if (isBrowser && config?.autoCreateConsents) {
167
+ config.consents = getConsentsWaitForAnalytics((consents) => {
168
+ logger.debug('Consents received from CMP', consents);
169
+ return this.setConsentsInternal(consents);
170
+ });
171
+ }
172
+ if (isPromise(config?.consents)) {
173
+ includeAdvertising = applyAdvertisingConsent(config?.consents, config?.requireAdvertisingOptIn);
174
+ }
175
+ else {
176
+ includeAdvertising = applyAdvertisingConsentSync(config?.consents, config?.requireAdvertisingOptIn);
177
+ }
178
+ // TODO: this check should not be necessary. The config should be mandatory as a type, fix it in the future
179
+ if (config) {
180
+ config.nativeJwe = getDefaultNativeJwe(config);
181
+ config.altEventHandler = getDefaultAltHandler(config);
182
+ }
183
+ isCisInConfig = Boolean(config?.cisBaseUrl);
184
+ isCollectorInConfig = Boolean(config?.collectorBaseUrl);
185
+ identity.clearCookieJweIfStale(config?.nativeJwe);
186
+ const deployStage = config?.deployStage || 'pro';
187
+ const deployStageTpaas = config?.deployStageTpaas || 'pre';
188
+ this.state = pulseMerge({}, defaultConfig, {
189
+ collectorBaseUrl: collectorEndpoints[deployStage],
190
+ deployStage,
191
+ deployStageTpaas,
192
+ fallbackCisBaseUrl: CISEndpoints[deployStage],
193
+ fallbackCollectorBaseUrl: collectorEndpoints[deployStage],
194
+ includeAdvertising,
195
+ isHybrid: isHybrid(config),
196
+ pageViewId: v4(),
197
+ providerId,
198
+ remoteConfigurationUrl: remoteConfig[deployStage],
199
+ schemaLocation: 'schema.schibsted.com',
200
+ tpaasCollectorBaseUrl: collectorEndpoints[deployStageTpaas],
201
+ trackerId: v4(),
202
+ vendors: config?.vendors?.length ? [] : ['xandr'],
203
+ }, config);
204
+ // Move to default config?
205
+ this.builders = pulseMerge({}, builders, {
206
+ provider: {
207
+ id: providerId,
208
+ },
209
+ tracker: {
210
+ version: version.SDK_VERSION,
211
+ },
212
+ });
213
+ this.bookmark = new Map();
214
+ // Replace with a linked list of Promises?
215
+ this.eventQueue = [];
216
+ this.retryEventQueue = [];
217
+ this.tpaasEventQueue = [];
218
+ this.anonymousEventQueue = [];
219
+ this.retryAnonymousEventQueue = [];
220
+ this.retryTpaasEventQueue = [];
221
+ if (this.state.environment === 'browser') {
222
+ // @ts-expect-error
223
+ if (isBrowser && window.navigator?.sendBeacon) {
224
+ const originalUseBeacon = this.state.useBeacon;
225
+ window.addEventListener('pagehide', () => {
226
+ this.state.useBeacon = true;
227
+ this._sendImmediately().then(() => {
228
+ void 0;
229
+ });
230
+ }, { capture: true });
231
+ window.addEventListener('pageshow', () => {
232
+ this.state.useBeacon = originalUseBeacon;
233
+ });
234
+ }
235
+ }
236
+ // @ts-expect-error
237
+ this.debouncedSend = throttle(async () => {
238
+ try {
239
+ return await this._sendImmediately();
240
+ }
241
+ catch (err) {
242
+ return err;
243
+ }
244
+ }, this.state.eventDebounce);
245
+ // @ts-expect-error
246
+ this.debouncedSendAnonymous = throttle(async () => {
247
+ try {
248
+ return await this._sendImmediatelyAnonymous();
249
+ }
250
+ catch (err) {
251
+ return err;
252
+ }
253
+ }, this.state.eventDebounce);
254
+ // @ts-expect-error
255
+ this.debouncedSendTpaas = throttle(async () => {
256
+ try {
257
+ return await this._sendImmediatelyTpaas();
258
+ }
259
+ catch (err) {
260
+ return err;
261
+ }
262
+ }, this.state.eventDebounce);
263
+ eventBus.emit('tracker:ready', { tracker: this });
264
+ }
265
+ /**
266
+ * Add event to the tracker event queue
267
+ *
268
+ * The input can be objects, arrays, primitives or promises. The
269
+ * order of calls to the method is not guaranteed to be sent in the same
270
+ * sequence.
271
+ *
272
+ * ```
273
+ * tracker.track('trackerEvent', {
274
+ * actor: new Promise(resolve => setTimeout(() => resolve('person@example.org'), 2000))
275
+ * });
276
+ * tracker.track('trackerEvent', { type: 'Engagement '});
277
+ *
278
+ * ```
279
+ *
280
+ * The second call to `track` will be added to the event queue before the
281
+ * first since all input to events are resolved before being added to the
282
+ * internal queue. Setting the future value in the SDK state will block all
283
+ * events and events will be added to the queue in order.
284
+ *
285
+ * ```
286
+ * tracker.update({
287
+ * actor: new Promise(resolve =>
288
+ * setTimeout(() => resolve('person@example.org'), 2000)) })
289
+ * tracker.track('trackerEvent', { type: 'View' });
290
+ * tracker.track('trackerEvent', { type: 'Engagement' });
291
+ * ```
292
+ *
293
+ * Both of these events will be blocked for two seconds and executed in order.
294
+ *
295
+ * @typeParam T Type of event to track
296
+ * @param eventType. See [spt-tracking/pulse-event-builders]() for
297
+ * available event types
298
+ * @param input. input input to the given event. The given input and the
299
+ * persisted input in the tracker will be merged before passing it to the event
300
+ * function.
301
+ * @param {TrackOptions} options
302
+ * @category Legacy Tracking
303
+ */
304
+ track(eventType, input, options) {
305
+ const currentBuilders = { ...this.builders };
306
+ const _track = async (trackResponse) => {
307
+ const createdEvent = this.createEvent(input);
308
+ return this.evaluateEvent(eventType, createdEvent, currentBuilders, options).then(async (event) => {
309
+ if (options?.bookmarkKey) {
310
+ this.bookmark.set(options.bookmarkKey, event);
311
+ }
312
+ // if we have an alternative handler defined, send events there
313
+ // instead of pushing them onto the queue.
314
+ if (this.state.altEventHandler) {
315
+ const handler = this.state.altEventHandler;
316
+ handler(JSON.stringify(event));
317
+ return Promise.resolve(trackResponse);
318
+ }
319
+ const queuedEvent = this._push(event, options).then(() => void 0);
320
+ await this.send();
321
+ return queuedEvent.then((result) => result);
322
+ });
323
+ };
324
+ return this.syncRemoteResources(input, currentBuilders).then(_track, _track);
325
+ }
326
+ /**
327
+ * Add anonymous event to the tracker anonymous event queue
328
+ *
329
+ * The input can be objects, arrays, primitives or promises. The
330
+ * order of calls to the method is not guaranteed to be sent in the same
331
+ * sequence.
332
+ *
333
+ * ```
334
+ * tracker.trackAnonymous('trackerEvent', { type: 'Engagement'});
335
+ * ```
336
+ *
337
+ * Anonymous events will not contain: `session`, `actor`, `device`, `location`, `pageViewId`.
338
+ *
339
+ * Anonymous events will always have the `isAnonymous` field set to true.
340
+ *
341
+ * Anonymous events will not await for consents. They will be applied if available, otherwise it will fall back to `unknown`.
342
+ *
343
+ * Considering the above, you should *not* add custom fields that can break anonymity.
344
+ *
345
+ * If you are missing consents, you're also not allowed to interact with storage or cookies for the purpose of these events.
346
+ * @typeParam T Type of event to track
347
+ * @param eventType.
348
+ * @param input. input input to the given event. The given input and the
349
+ * persisted input in the tracker will be merged before passing it to the event
350
+ * function.
351
+ * @param {TrackOptions} options
352
+ * @category Tracking Anonymous
353
+ */
354
+ async trackAnonymous(eventType, input, options) {
355
+ // We must create the event as soon as possible, as it defines the creationDate.
356
+ const newEvent = this.createAnonymousEvent(input);
357
+ // Remote config values ----------------
358
+ await this._applyRemoteConfigEndpoints();
359
+ // Resolve all available properties ----------------
360
+ const resolvedOutput = await Promise.all([this.resolveTrackInput(newEvent), this.resolveTrackGlobals()]);
361
+ let eventOutput = resolvedOutput.reduce((acc, p) => pulseMerge(acc, p), {});
362
+ eventOutput = this.applyAnonymousEventTypeDefaults(eventOutput, eventType);
363
+ // Leave Events ----------------
364
+ // they require (most) properties of the previous PageView event, which was saved under a bookmark key when tracked
365
+ eventOutput = this.applyBookmarkedEvent(eventOutput, options?.applyBookmarkKey);
366
+ // TCF Consents ----------------
367
+ eventOutput = this.applyConsentsAnonymous(eventOutput);
368
+ // Build the entire event----------------
369
+ // Depending on the event type, like Tracker or Engagement.
370
+ eventOutput = getAnonymousEventBuilder(eventType)({
371
+ eventInput: eventOutput,
372
+ sdkConfig: this.state,
373
+ });
374
+ if (options?.bookmarkKey) {
375
+ this.bookmark.set(options.bookmarkKey, eventOutput);
376
+ }
377
+ // Dispatch ----------------
378
+ // The Hybrid use case implements a "bridged" event method, injected into the window scope,
379
+ // which is used to send events through the native app.
380
+ if (this.state.altEventHandler) {
381
+ this.state.altEventHandler(JSON.stringify(eventOutput));
382
+ return eventOutput;
383
+ }
384
+ const queuedEvent = this._pushAnonymous(eventOutput, options);
385
+ await this.sendAnonymous();
386
+ return queuedEvent;
387
+ }
388
+ async adaptExperiments(baseExperiments = []) {
389
+ return baseExperiments.map((exp) => {
390
+ return {
391
+ name: exp.name || exp.id,
392
+ variant: exp.variant || '',
393
+ };
394
+ });
395
+ }
396
+ /**
397
+ *
398
+ * @private
399
+ * @category TPaaS Tracking
400
+ */
401
+ async prepareAnonymousTpaasEvent() {
402
+ try {
403
+ await this._applyRemoteConfigEndpoints();
404
+ }
405
+ catch (ex) {
406
+ logger.trace('Failed to sync remote config', ex);
407
+ }
408
+ return {
409
+ autoTrackerVersion: this.builders.tracker?.autoTrackerVersion,
410
+ version: version.SDK_VERSION,
411
+ isHybrid: !!this.state.isHybrid,
412
+ pageviewId: this.state.pageViewId,
413
+ providerId: this.state.providerId,
414
+ experiments: await this.adaptExperiments(this.builders.experiments),
415
+ };
416
+ }
417
+ /**
418
+ *
419
+ * @private
420
+ * @category TPaaS Tracking
421
+ */
422
+ async prepareTpaasEvent() {
423
+ try {
424
+ await this.syncRemoteResources(undefined, { ...this.builders });
425
+ }
426
+ catch (ex) {
427
+ logger.trace('Failed to sync remote resources', ex);
428
+ // remote config and CIS failures are also ignored for the old track() method. doing the same here
429
+ }
430
+ function adaptActorToNewFormat(actor) {
431
+ // this is a temporary solution to adapt the actor to the new format
432
+ // it should be removed once we have new methods in place to get the actor
433
+ if (!actor) {
434
+ return;
435
+ }
436
+ return {
437
+ id: actor.id?.toString() || '',
438
+ realm: actor.realm || '',
439
+ hasAnySubscription: !!actor.hasAnySubscription,
440
+ region: isString(actor.region) ? actor.region : undefined,
441
+ };
442
+ }
443
+ function adaptConsentsToNewFormat(consents) {
444
+ if (!consents) {
445
+ return;
446
+ }
447
+ const { purposes, source } = consents;
448
+ const { CMP_ADVERTISING, CMP_ANALYTICS, CMP_MARKETING, CMP_PERSONALIZATION } = purposes;
449
+ function adaptStatusOrOptIn({ status, optIn }) {
450
+ // doing an unnecessary check for status here
451
+ // because otherwise the code after the switch will be marked as unreachable in the IDE
452
+ if (status) {
453
+ switch (status) {
454
+ case 'accepted':
455
+ return 'Accepted';
456
+ case 'rejected':
457
+ return 'Rejected';
458
+ case 'unknown':
459
+ return 'Unknown';
460
+ }
461
+ }
462
+ if (optIn === true) {
463
+ return 'Accepted';
464
+ }
465
+ if (optIn === false) {
466
+ return 'Rejected';
467
+ }
468
+ return 'Unknown';
469
+ }
470
+ return {
471
+ advertising: adaptStatusOrOptIn(CMP_ADVERTISING),
472
+ analytics: adaptStatusOrOptIn(CMP_ANALYTICS),
473
+ marketing: adaptStatusOrOptIn(CMP_MARKETING),
474
+ personalization: adaptStatusOrOptIn(CMP_PERSONALIZATION),
475
+ source: source || 'unknown',
476
+ };
477
+ }
478
+ const [actor, consents, experiments] = await Promise.all([
479
+ this.getActor(),
480
+ this.getConsents(),
481
+ this.adaptExperiments(this.builders.experiments),
482
+ ]);
483
+ const { environmentId, jwe } = parsePulseCookies();
484
+ return {
485
+ autoTrackerVersion: this.builders.tracker?.autoTrackerVersion,
486
+ version: version.SDK_VERSION,
487
+ isHybrid: !!this.state.isHybrid,
488
+ user: adaptActorToNewFormat(actor),
489
+ consents: adaptConsentsToNewFormat(consents),
490
+ providerId: this.state.providerId,
491
+ pageviewId: this.state.pageViewId,
492
+ currentPage: this.currentPage,
493
+ experiments,
494
+ environmentId,
495
+ jwe,
496
+ };
497
+ }
498
+ /**
499
+ * Generate a generic TPaaS event with common builders output
500
+ * The method should be used for experiments, not for real production work.
501
+ * It doesn't have any real TPaaS schema associated with it.
502
+ * The method doesn't queue or send the event, it just returns the merged object.
503
+ * The method can be removed at any time in the future, so use it with caution.
504
+ *
505
+ * @param input - The input object to merge with the common builders output
506
+ * @returns A promise that resolves to the merged object
507
+ * @private
508
+ * @category TPaaS Tracking
509
+ */
510
+ async generateGenericTpaasEvent(input) {
511
+ const dependencies = await this.prepareTpaasEvent();
512
+ return pulseMerge({}, input, getCommonBuildersOutput(new Date(), dependencies));
513
+ }
514
+ /**
515
+ * This method extends the list of base experiments that will be automatically included in every event sent by the tracker.
516
+ *
517
+ * It accepts:
518
+ * - An array of experiments and/or promises resolving to the experiments
519
+ * - A Promise resolving to an array of experiments
520
+ *
521
+ * This allows to easily manage experiments without having to repeat them in every tracking call. For example:
522
+ *
523
+ * ```ts
524
+ * const experiments = [{ id: 'experiment-A', variant: 'blue-button' }];
525
+ *
526
+ * tracker.addExperiments(experiments);
527
+ * ```
528
+
529
+ Calling the method multiple times concatenates all given experiments and stores them as base experiments. Experiments can be either direct values or Promises, and they will be included in all future tracking events.
530
+
531
+ * @param experiments
532
+ * @category Tracking
533
+ */
534
+ addExperiments(experiments) {
535
+ this.update({ experiments }, true);
536
+ }
537
+ /**
538
+ * The `addUIElementVisibilityTracking` function provides an interface for sending tracking events when specific UI elements become visible within the viewport.
539
+ * It is built on the `VisibilityObserver` class, which efficiently detects visibility changes in DOM elements.
540
+ * When an element becomes at least 2/3 visible, a callback is triggered to process the element and create a tracking event.
541
+ * It leverages the [Intersection Observer API](https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API) for viewport tracking
542
+ * and the [Mutation Observer API](https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver) to monitor lazy-loaded elements.
543
+ *
544
+ * Example usage:
545
+ *
546
+ * ```ts
547
+ * addUIElementVisibilityTracking('[data-pulse-entity-id]', (element) => {
548
+ * const target = createPulseTarget(element);
549
+ * const object = createPulseObject(element);
550
+ *
551
+ * return { object, target };
552
+ * });
553
+ * ```
554
+ *
555
+ * @param {string} selector - CSS selector for elements to track.
556
+ * @param {Function} buildEventFromElement - Function to build event object when element is visible.
557
+ * @deprecated This only works for legacy events. For TPaaS events, use `addUIElementVisibilityTracking` instead.
558
+ * @category Legacy Tracking
559
+ */
560
+ addLegacyUIElementVisibilityTracking(selector, buildEventFromElement) {
561
+ if (this.legacyVisibilityObservers.has(selector)) {
562
+ console.warn(`Cannot add UI Element visibility tracking for selector "${selector}" as it is already being tracked.`);
563
+ return;
564
+ }
565
+ this.legacyVisibilityObservers.set(selector, new VisibilityObserver((element) => {
566
+ const viewUIElementInputProperties = buildEventFromElement(element);
567
+ this.trackLegacyViewUIElement(viewUIElementInputProperties);
568
+ }));
569
+ this.legacyVisibilityObservers.get(selector)?.observe(selector);
570
+ }
571
+ /**
572
+ * The `addUIElementVisibilityTracking` function provides an interface for sending tracking events when specific UI elements become visible within the viewport.
573
+ * It is built on the `VisibilityObserver` class, which efficiently detects visibility changes in DOM elements.
574
+ * When an element becomes at least 2/3 visible, a callback is triggered to process the element and create a tracking event.
575
+ * It leverages the [Intersection Observer API](https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API) for viewport tracking
576
+ * and the [Mutation Observer API](https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver) to monitor lazy-loaded elements.
577
+ *
578
+ * Example usage:
579
+ *
580
+ * ```ts
581
+ * addUIElementVisibilityTracking('[data-pulse-entity-id]', (element) => {
582
+ * const eventInput = createEventInput(element);
583
+ *
584
+ * return eventInput;
585
+ * });
586
+ * ```
587
+ *
588
+ * @param {string} selector - CSS selector for elements to track.
589
+ * @param {Function} buildEventFromElement - Function to build event object when element is visible.
590
+ * @category Tracking
591
+ */
592
+ addUIElementVisibilityTracking(selector, buildEventFromElement) {
593
+ if (this.visibilityObservers.has(selector)) {
594
+ console.warn(`Cannot add UI Element visibility tracking for selector "${selector}" as it is already being tracked.`);
595
+ return;
596
+ }
597
+ this.visibilityObservers.set(selector, new VisibilityObserver((element) => {
598
+ const eventInput = buildEventFromElement(element);
599
+ this.trackImpressionUIElement(eventInput);
600
+ }));
601
+ this.visibilityObservers.get(selector)?.observe(selector);
602
+ }
603
+ /**
604
+ * The old trackViewArticle method from the Media Wrapper.
605
+ * When triggering this page-view function, both the "page" object and "origin"
606
+ * will be stored and re-used across subsequent events.
607
+ *
608
+ * @param inputProperties
609
+ * @param trackOptions
610
+ * @category Legacy Tracking
611
+ */
612
+ trackLegacyViewArticle(inputProperties, trackOptions) {
613
+ const viewArticleEventData = buildLegacyViewArticleEvent(inputProperties);
614
+ this.setPageDefaults(viewArticleEventData);
615
+ return this.trackPageView(viewArticleEventData, trackOptions);
616
+ }
617
+ /**
618
+ * The old trackViewLoginPoster method from the Media Wrapper.
619
+ * When triggering this page-view function, both the "page" object and "origin"
620
+ * will be stored and re-used across subsequent events.
621
+ *
622
+ * @param inputProperties
623
+ * @param trackOptions
624
+ * @category Legacy Tracking
625
+ */
626
+ trackLegacyViewLoginPoster(inputProperties, trackOptions) {
627
+ const viewLoginPosterEventData = buildViewLoginPosterEvent(inputProperties);
628
+ this.setPageDefaults(viewLoginPosterEventData);
629
+ return this.trackPageView(viewLoginPosterEventData, trackOptions);
630
+ }
631
+ /**
632
+ * The old trackViewSalesPoster method from the Media Wrapper.
633
+ * When triggering this page-view function, both the "page" object and "origin"
634
+ * will be stored and re-used across subsequent events.
635
+ *
636
+ * @param inputProperties
637
+ * @param trackOptions
638
+ * @category Legacy Tracking
639
+ */
640
+ trackLegacyViewSalesPoster(inputProperties, trackOptions) {
641
+ const viewSalesposterEventData = buildViewSalesPosterEvent(inputProperties);
642
+ this.setPageDefaults(viewSalesposterEventData);
643
+ return this.trackPageView(viewSalesposterEventData, trackOptions);
644
+ }
645
+ /**
646
+ * The old trackViewListing method from the Media Wrapper.
647
+ * When triggering this page-view function, both the "page" object and "origin"
648
+ * will be stored and re-used across subsequent events.
649
+ *
650
+ * @param inputProperties
651
+ * @param trackOptions
652
+ * @category Legacy Tracking
653
+ */
654
+ trackLegacyViewListing(inputProperties, trackOptions) {
655
+ const viewListingEventData = buildLegacyViewListingEvent(inputProperties);
656
+ this.setPageDefaults(viewListingEventData);
657
+ return this.trackPageView(viewListingEventData, trackOptions);
658
+ }
659
+ /**
660
+ * The old trackViewFrontpage method from the Media Wrapper.
661
+ * When triggering this page-view function, both the "page" object and "origin"
662
+ * will be stored and re-used across subsequent events.
663
+ *
664
+ * @param inputProperties
665
+ * @param trackOptions
666
+ * @category Legacy Tracking
667
+ */
668
+ trackLegacyViewFrontpage(inputProperties, trackOptions) {
669
+ const viewFrontpageEventData = buildLegacyViewFrontpageEvent(inputProperties);
670
+ this.setPageDefaults(viewFrontpageEventData);
671
+ return this.trackPageView(viewFrontpageEventData, trackOptions);
672
+ }
673
+ /**
674
+ * The old trackViewPage method from the Media Wrapper.
675
+ * When triggering this page-view function, both the "page" object and "origin"
676
+ * will be stored and re-used across subsequent events.
677
+ *
678
+ * @param inputProperties
679
+ * @param trackOptions
680
+ * @category Legacy Tracking
681
+ */
682
+ trackLegacyViewPage(inputProperties, trackOptions) {
683
+ const pageViewEventData = buildLegacyViewPageEvent(inputProperties);
684
+ this.setPageDefaults(pageViewEventData);
685
+ return this.trackPageView(pageViewEventData, trackOptions);
686
+ }
687
+ /**
688
+ * The old trackViewUIElement method from the Media Wrapper.
689
+ *
690
+ * @param inputProperties
691
+ * @param trackOptions
692
+ * @category Legacy Tracking
693
+ */
694
+ trackLegacyViewUIElement(inputProperties, trackOptions) {
695
+ const viewUIElementEventData = buildLegacyViewUIElementEvent(inputProperties, this.legacyCurrentPage);
696
+ return this.track('trackerEvent', viewUIElementEventData, trackOptions);
697
+ }
698
+ /**
699
+ * The old trackClickUIElement method from the Media Wrapper.
700
+ *
701
+ * @param inputProperties
702
+ * @param trackOptions
703
+ * @category Legacy Tracking
704
+ */
705
+ trackLegacyClickUIElement(inputProperties, trackOptions) {
706
+ const clickUIElementEventData = buildClickUIElementEvent(inputProperties, this.legacyCurrentPage);
707
+ return this.track('trackerEvent', clickUIElementEventData, trackOptions);
708
+ }
709
+ /**
710
+ * The following methods are the track methods specific for the TPaaS schemas
711
+ */
712
+ /**
713
+ * @param input
714
+ * @category TPaaS Tracking
715
+ */
716
+ async trackAnonymousViewUIElement(input) {
717
+ const dependencies = await this.prepareAnonymousTpaasEvent();
718
+ const event = buildAnonymousViewUIElementEvent(input, dependencies);
719
+ return this.sendTpaasEvent(event);
720
+ }
721
+ async trackCompletedHealthAction(input) {
722
+ const dependencies = await this.prepareTpaasEvent();
723
+ const event = buildCompletedHealthActionEvent(input, dependencies);
724
+ return this.sendTpaasEvent(event);
725
+ }
726
+ async trackEngagementHealthUIElement(input) {
727
+ const dependencies = await this.prepareTpaasEvent();
728
+ const event = buildEngagementHealthUIElementEvent(input, dependencies);
729
+ return this.sendTpaasEvent(event);
730
+ }
731
+ async trackViewHealthPage(input, options) {
732
+ this.newPageView(); // Reset the page view ID if it is not set, to ensure a new page view is tracked
733
+ this.setCurrentPage(input.object.objectId, 'Page'); // ViewHealthPage.object.objectType is HealthPage, which is not allowed as a pageType
734
+ const dependencies = await this.prepareTpaasEvent();
735
+ const event = buildViewHealthPageEvent(input, dependencies);
736
+ const result = this.sendTpaasEvent(event);
737
+ if (shouldEnableLeaveTracking(options.leaveTracking)) {
738
+ const { objectElement, pageElement, heightBuilder, objectResizable } = options.leaveTracking;
739
+ // HealthView Page is a bit special, in the sense that in doesn't have a dedicated Leave event.
740
+ // Instead, we need to reuse the generic Leave Page event, but adapt the input accordingly.
741
+ // This means omitting some fields from HealthView Page that are not part of Leave Page schema.
742
+ const { experiments, metrics, object, ...restInput } = input;
743
+ const { category, custom, intent, name, tags, ...restObject } = input.object;
744
+ const leavePageCallback = (leave) => {
745
+ this.trackLeavePage({
746
+ leave,
747
+ ...restInput,
748
+ object: {
749
+ ...restObject,
750
+ title: restObject.title || '',
751
+ },
752
+ });
753
+ };
754
+ addTpaasLeaveTracking({
755
+ objectElement,
756
+ pageElement,
757
+ objectResizable,
758
+ heightBuilder,
759
+ schema: LeavePage.object.objectType,
760
+ trackMethod: leavePageCallback,
761
+ });
762
+ }
763
+ return result;
764
+ }
765
+ async trackImpressionHealthUIElement(input) {
766
+ const dependencies = await this.prepareTpaasEvent();
767
+ const event = buildImpressionHealthUIElementEvent(input, dependencies);
768
+ return this.sendTpaasEvent(event);
769
+ }
770
+ /**
771
+ * @param input
772
+ * @param options
773
+ * @category TPaaS Tracking
774
+ */
775
+ async trackViewPage(input, options) {
776
+ this.newPageView(); // Reset the page view ID if it is not set, to ensure a new page view is tracked
777
+ this.setCurrentPage(input.object.objectId, ViewPage.object.objectType);
778
+ const dependencies = await this.prepareTpaasEvent();
779
+ const event = buildViewPageEvent(input, dependencies);
780
+ const result = this.sendTpaasEvent(event);
781
+ if (shouldEnableLeaveTracking(options.leaveTracking)) {
782
+ const { objectElement, pageElement, heightBuilder, objectResizable } = options.leaveTracking;
783
+ const leavePageCallback = (leave) => {
784
+ this.trackLeavePage({
785
+ leave,
786
+ ...input,
787
+ });
788
+ };
789
+ addTpaasLeaveTracking({
790
+ objectElement,
791
+ pageElement,
792
+ objectResizable,
793
+ heightBuilder,
794
+ schema: LeavePage.object.objectType,
795
+ trackMethod: leavePageCallback,
796
+ });
797
+ }
798
+ return result;
799
+ }
800
+ /**
801
+ * @param input
802
+ * @category TPaaS Tracking
803
+ */
804
+ async trackViewTitle(input) {
805
+ this.newPageView(); // Reset the page view ID if it is not set, to ensure a new page view is tracked
806
+ this.setCurrentPage(input.object.objectId, ViewTitle.object.objectType);
807
+ const dependencies = await this.prepareTpaasEvent();
808
+ const event = buildViewTitleEvent(input, dependencies);
809
+ return this.sendTpaasEvent(event);
810
+ // there's no Leave Title event
811
+ }
812
+ /**
813
+ * @param input
814
+ * @category TPaaS Tracking
815
+ */
816
+ async trackImpressionWidget(input) {
817
+ const dependencies = await this.prepareTpaasEvent();
818
+ const event = buildImpressionWidgetEvent(input, dependencies);
819
+ return this.sendTpaasEvent(event);
820
+ }
821
+ /**
822
+ * @param input
823
+ * @category TPaaS Tracking
824
+ */
825
+ async trackImpressionAdSlot(input) {
826
+ const dependencies = await this.prepareTpaasEvent();
827
+ const event = buildImpressionAdSlotEvent(input, dependencies);
828
+ return this.sendTpaasEvent(event);
829
+ }
830
+ /**
831
+ * @param input
832
+ * @param options
833
+ * @category TPaaS Tracking
834
+ */
835
+ async trackViewArticle(input, options) {
836
+ this.newPageView(); // Reset the page view ID if it is not set, to ensure a new page view is tracked
837
+ this.setCurrentPage(input.object.objectId, ViewArticle.object.objectType);
838
+ const dependencies = await this.prepareTpaasEvent();
839
+ const event = buildViewArticleEvent(input, dependencies);
840
+ const result = this.sendTpaasEvent(event);
841
+ if (shouldEnableLeaveTracking(options.leaveTracking)) {
842
+ const { objectElement, pageElement, heightBuilder, objectResizable } = options.leaveTracking;
843
+ const leaveArticleCallback = (leave) => {
844
+ this.trackLeaveArticle({
845
+ leave,
846
+ ...input,
847
+ });
848
+ };
849
+ addTpaasLeaveTracking({
850
+ objectElement,
851
+ pageElement,
852
+ heightBuilder,
853
+ objectResizable,
854
+ schema: LeaveArticle.object.objectType,
855
+ trackMethod: leaveArticleCallback,
856
+ });
857
+ }
858
+ return result;
859
+ }
860
+ /**
861
+ * @param input
862
+ * @param options
863
+ * @category TPaaS Tracking
864
+ */
865
+ async trackViewAudio(input) {
866
+ // despite the View event type, this is not a page view event, but rather a media object view event
867
+ // so we shouldn't reset the page view ID here or enable leave tracking
868
+ const dependencies = await this.prepareTpaasEvent();
869
+ const event = buildViewAudioEvent(input, dependencies);
870
+ return this.sendTpaasEvent(event);
871
+ }
872
+ /**
873
+ * Tracks a View AudioPage event and automatically fires a Leave AudioPage event when the user
874
+ * navigates away.
875
+ *
876
+ * The Leave AudioPage event requires audio engagement statistics (`leaveAudio`) that the SDK
877
+ * cannot compute on its own. Provide a `leaveAudioBuilder` callback in the `leaveTracking`
878
+ * options — it is called at leave time (not at registration time), so it always captures the
879
+ * latest state. If no builder is supplied all audio engagement fields default to `0`.
880
+ *
881
+ * `activityDurationMs` and `durationMs` are computed by the leave tracking system and must
882
+ * **not** be included in the value returned by `leaveAudioBuilder`.
883
+ *
884
+ * @example
885
+ * ```ts
886
+ * // Minimal — leave fires with zeroed audio stats
887
+ * await tracker.trackViewAudioPage(input, {
888
+ * leaveTracking: { objectElement: document.getElementById('audio-player')! },
889
+ * });
890
+ *
891
+ * // With leaveAudioBuilder — capture live playback stats at leave time
892
+ * await tracker.trackViewAudioPage(input, {
893
+ * leaveTracking: {
894
+ * objectElement: document.getElementById('audio-player')!,
895
+ * leaveAudioBuilder: () => ({
896
+ * audioStarted: player.tracksStarted,
897
+ * audioCompleted: player.tracksCompleted,
898
+ * maxPlaylistPosition: player.maxPosition,
899
+ * playlistPositionPercentage: player.positionPercentage,
900
+ * }),
901
+ * },
902
+ * });
903
+ *
904
+ * // Disable leave tracking entirely
905
+ * await tracker.trackViewAudioPage(input, { leaveTracking: false });
906
+ * ```
907
+ *
908
+ * @param input
909
+ * @param options
910
+ * @category TPaaS Tracking
911
+ */
912
+ async trackViewAudioPage(input, options) {
913
+ this.newPageView();
914
+ this.setCurrentPage(input.object.objectId, 'Audio'); // ViewAudioPage.object.objectType is AudioPage, which is not allowed as a pageType
915
+ const dependencies = await this.prepareTpaasEvent();
916
+ const event = buildViewAudioPageEvent(input, dependencies);
917
+ const result = this.sendTpaasEvent(event);
918
+ if (shouldEnableLeaveTracking(options.leaveTracking)) {
919
+ const { objectElement, pageElement, heightBuilder, objectResizable, leaveAudioBuilder } = options.leaveTracking;
920
+ const leaveAudioPageCallback = (leave) => {
921
+ const leaveAudioInput = leaveAudioBuilder?.() ?? {
922
+ audioCompleted: 0,
923
+ audioStarted: 0,
924
+ maxPlaylistPosition: 0,
925
+ playlistPositionPercentage: 0,
926
+ };
927
+ this.trackLeaveAudioPage({
928
+ leave,
929
+ leaveAudio: {
930
+ ...leaveAudioInput,
931
+ activityDurationMs: leave.activityDurationMs,
932
+ durationMs: leave.durationMs,
933
+ },
934
+ ...input,
935
+ });
936
+ };
937
+ addTpaasLeaveTracking({
938
+ objectElement,
939
+ pageElement,
940
+ heightBuilder,
941
+ objectResizable,
942
+ schema: LeaveAudioPage.object.objectType,
943
+ trackMethod: leaveAudioPageCallback,
944
+ });
945
+ }
946
+ return result;
947
+ }
948
+ /**
949
+ * @param input
950
+ * @param options
951
+ * @category TPaaS Tracking
952
+ */
953
+ async trackViewError(input, options) {
954
+ this.newPageView(); // Reset the page view ID if it is not set, to ensure a new page view is tracked
955
+ this.setCurrentPage(input.object.objectId, ViewError.object.objectType);
956
+ const dependencies = await this.prepareTpaasEvent();
957
+ const event = buildViewErrorEvent(input, dependencies);
958
+ const result = this.sendTpaasEvent(event);
959
+ if (shouldEnableLeaveTracking(options.leaveTracking)) {
960
+ const { objectElement, pageElement, heightBuilder, objectResizable } = options.leaveTracking;
961
+ const leaveErrorCallback = (leave) => {
962
+ this.trackLeaveError({
963
+ leave,
964
+ ...input,
965
+ });
966
+ };
967
+ addTpaasLeaveTracking({
968
+ objectElement,
969
+ pageElement,
970
+ heightBuilder,
971
+ objectResizable,
972
+ schema: LeaveError.object.objectType,
973
+ trackMethod: leaveErrorCallback,
974
+ });
975
+ }
976
+ return result;
977
+ }
978
+ /**
979
+ * @param input
980
+ * @category TPaaS Tracking
981
+ */
982
+ async trackImpressionForm(input) {
983
+ const dependencies = await this.prepareTpaasEvent();
984
+ const event = buildImpressionFormEvent(input, dependencies);
985
+ return this.sendTpaasEvent(event);
986
+ }
987
+ /**
988
+ * @param input
989
+ * @category TPaaS Tracking
990
+ */
991
+ async trackImpressionOffer(input) {
992
+ const dependencies = await this.prepareTpaasEvent();
993
+ const event = buildImpressionOfferEvent(input, dependencies);
994
+ return this.sendTpaasEvent(event);
995
+ }
996
+ /**
997
+ * @param input
998
+ * @category TPaaS Tracking
999
+ */
1000
+ async trackImpressionPlayer(input) {
1001
+ const dependencies = await this.prepareTpaasEvent();
1002
+ const event = buildImpressionPlayerEvent(input, dependencies);
1003
+ return this.sendTpaasEvent(event);
1004
+ }
1005
+ /**
1006
+ * @param input
1007
+ * @category TPaaS Tracking
1008
+ */
1009
+ async trackImpressionTeaser(input) {
1010
+ const dependencies = await this.prepareTpaasEvent();
1011
+ const event = buildImpressionTeaserEvent(input, dependencies);
1012
+ return this.sendTpaasEvent(event);
1013
+ }
1014
+ /**
1015
+ * @param input
1016
+ * @category TPaaS Tracking
1017
+ */
1018
+ async trackImpressionUIElement(input) {
1019
+ const dependencies = await this.prepareTpaasEvent();
1020
+ const event = buildImpressionUIElementEvent(input, dependencies);
1021
+ return this.sendTpaasEvent(event);
1022
+ }
1023
+ /**
1024
+ * @param input
1025
+ * @param options
1026
+ * @category TPaaS Tracking
1027
+ */
1028
+ async trackViewFrontpage(input, options) {
1029
+ this.newPageView(); // Reset the page view ID if it is not set, to ensure a new page view is tracked
1030
+ this.setCurrentPage(input.object.objectId, ViewFrontpage.object.objectType);
1031
+ const dependencies = await this.prepareTpaasEvent();
1032
+ const event = buildViewFrontpageEvent(input, dependencies);
1033
+ const result = this.sendTpaasEvent(event);
1034
+ if (shouldEnableLeaveTracking(options.leaveTracking)) {
1035
+ const { objectElement, pageElement, heightBuilder, objectResizable } = options.leaveTracking;
1036
+ const leaveFrontpageCallback = (leave) => {
1037
+ this.trackLeaveFrontpage({
1038
+ leave,
1039
+ ...input,
1040
+ });
1041
+ };
1042
+ addTpaasLeaveTracking({
1043
+ objectElement,
1044
+ pageElement,
1045
+ objectResizable,
1046
+ heightBuilder,
1047
+ schema: LeaveFrontpage.object.objectType,
1048
+ trackMethod: leaveFrontpageCallback,
1049
+ });
1050
+ }
1051
+ return result;
1052
+ }
1053
+ /**
1054
+ * @param input
1055
+ * @param options
1056
+ * @category TPaaS Tracking
1057
+ */
1058
+ async trackViewLandingpage(input, options) {
1059
+ this.newPageView(); // Reset the page view ID if it is not set, to ensure a new page view is tracked
1060
+ this.setCurrentPage(input.object.objectId, 'LandingPage' /* TODO: ViewLandingpage.object.type once the schema is fixed */);
1061
+ const dependencies = await this.prepareTpaasEvent();
1062
+ const event = buildViewLandingpageEvent(input, dependencies);
1063
+ const result = this.sendTpaasEvent(event);
1064
+ if (shouldEnableLeaveTracking(options.leaveTracking)) {
1065
+ const { objectElement, pageElement, heightBuilder, objectResizable } = options.leaveTracking;
1066
+ const leaveLandingpageCallback = (leave) => {
1067
+ this.trackLeaveLandingpage({
1068
+ leave,
1069
+ ...input,
1070
+ });
1071
+ };
1072
+ addTpaasLeaveTracking({
1073
+ objectElement,
1074
+ pageElement,
1075
+ heightBuilder,
1076
+ objectResizable,
1077
+ schema: LeaveLandingpage.object.objectType,
1078
+ trackMethod: leaveLandingpageCallback,
1079
+ });
1080
+ }
1081
+ return result;
1082
+ }
1083
+ /**
1084
+ * @param input
1085
+ * @param options
1086
+ * @category TPaaS Tracking
1087
+ */
1088
+ async trackViewListing(input, options) {
1089
+ this.newPageView(); // Reset the page view ID if it is not set, to ensure a new page view is tracked
1090
+ this.setCurrentPage(input.object.objectId, ViewListing.object.objectType);
1091
+ const dependencies = await this.prepareTpaasEvent();
1092
+ const event = buildViewListingEvent(input, dependencies);
1093
+ const result = this.sendTpaasEvent(event);
1094
+ if (shouldEnableLeaveTracking(options.leaveTracking)) {
1095
+ const { objectElement, pageElement, heightBuilder, objectResizable } = options.leaveTracking;
1096
+ const leaveListingCallback = (leave) => {
1097
+ this.trackLeaveListing({
1098
+ leave,
1099
+ ...input,
1100
+ });
1101
+ };
1102
+ addTpaasLeaveTracking({
1103
+ objectElement,
1104
+ pageElement,
1105
+ heightBuilder,
1106
+ objectResizable,
1107
+ schema: LeaveListing.object.objectType,
1108
+ trackMethod: leaveListingCallback,
1109
+ });
1110
+ }
1111
+ return result;
1112
+ }
1113
+ /**
1114
+ * @param input
1115
+ * @param options
1116
+ * @category TPaaS Tracking
1117
+ */
1118
+ async trackViewLockedArticle(input, options) {
1119
+ this.newPageView(); // Reset the page view ID if it is not set, to ensure a new page view is tracked
1120
+ this.setCurrentPage(input.object.objectId, ViewLockedArticle.object.objectType);
1121
+ const dependencies = await this.prepareTpaasEvent();
1122
+ const event = buildViewLockedArticleEvent(input, dependencies);
1123
+ const result = this.sendTpaasEvent(event);
1124
+ if (shouldEnableLeaveTracking(options.leaveTracking)) {
1125
+ const { objectElement, pageElement, heightBuilder, objectResizable } = options.leaveTracking;
1126
+ const leaveLockedArticleCallback = (leave) => {
1127
+ this.trackLeaveLockedArticle({
1128
+ leave,
1129
+ ...input,
1130
+ });
1131
+ };
1132
+ addTpaasLeaveTracking({
1133
+ objectElement,
1134
+ pageElement,
1135
+ objectResizable,
1136
+ heightBuilder,
1137
+ schema: LeaveLockedArticle.object.objectType,
1138
+ trackMethod: leaveLockedArticleCallback,
1139
+ });
1140
+ }
1141
+ return result;
1142
+ }
1143
+ /**
1144
+ * @param input
1145
+ * @param options
1146
+ * @category TPaaS Tracking
1147
+ */
1148
+ async trackViewLockedAudio(input) {
1149
+ // despite the View event type, this is not a page view event, but rather a media object view event
1150
+ // so we shouldn't reset the page view ID here or enable leave tracking
1151
+ const dependencies = await this.prepareTpaasEvent();
1152
+ const event = buildViewLockedAudioEvent(input, dependencies);
1153
+ return this.sendTpaasEvent(event);
1154
+ }
1155
+ /**
1156
+ * @param input
1157
+ * @param options
1158
+ * @category TPaaS Tracking
1159
+ */
1160
+ async trackViewLockedAudioPage(input, options) {
1161
+ this.newPageView();
1162
+ this.setCurrentPage(input.object.objectId, 'Audio'); // ViewLockedAudioPage.object.objectType is AudioPage, which is not allowed as a pageType
1163
+ const dependencies = await this.prepareTpaasEvent();
1164
+ const event = buildViewLockedAudioPageEvent(input, dependencies);
1165
+ const result = this.sendTpaasEvent(event);
1166
+ if (shouldEnableLeaveTracking(options.leaveTracking)) {
1167
+ const { objectElement, pageElement, heightBuilder, objectResizable } = options.leaveTracking;
1168
+ const leaveLockedAudioPageCallback = (leave) => {
1169
+ this.trackLeaveLockedAudioPage({
1170
+ leave,
1171
+ ...input,
1172
+ });
1173
+ };
1174
+ addTpaasLeaveTracking({
1175
+ objectElement,
1176
+ pageElement,
1177
+ heightBuilder,
1178
+ objectResizable,
1179
+ schema: LeaveLockedAudioPage.object.objectType,
1180
+ trackMethod: leaveLockedAudioPageCallback,
1181
+ });
1182
+ }
1183
+ return result;
1184
+ }
1185
+ /**
1186
+ * @param input
1187
+ * @category TPaaS Tracking
1188
+ */
1189
+ async trackViewLockedVideo(input) {
1190
+ // despite the name, this is not a page-level event. trackViewLockedVideoPage is a page-level event
1191
+ // as such, we don't support (yet) automatic leave event enabling
1192
+ const dependencies = await this.prepareTpaasEvent();
1193
+ const event = buildViewLockedVideoEvent(input, dependencies);
1194
+ return this.sendTpaasEvent(event);
1195
+ }
1196
+ /**
1197
+ * @param input
1198
+ * @param options
1199
+ * @category TPaaS Tracking
1200
+ */
1201
+ async trackViewLockedVideoPage(input, options) {
1202
+ this.newPageView(); // Reset the page view ID if it is not set, to ensure a new page view is tracked
1203
+ this.setCurrentPage(input.object.objectId, ViewLockedVideo.object.objectType);
1204
+ const dependencies = await this.prepareTpaasEvent();
1205
+ const event = buildViewLockedVideoPageEvent(input, dependencies);
1206
+ const result = this.sendTpaasEvent(event);
1207
+ if (shouldEnableLeaveTracking(options.leaveTracking)) {
1208
+ const { objectElement, pageElement, heightBuilder, objectResizable } = options.leaveTracking;
1209
+ const leaveLockedVideoPageCallback = (leave) => {
1210
+ this.trackLeaveLockedVideoPage({
1211
+ leave,
1212
+ ...input,
1213
+ });
1214
+ };
1215
+ addTpaasLeaveTracking({
1216
+ objectElement,
1217
+ pageElement,
1218
+ heightBuilder,
1219
+ objectResizable,
1220
+ schema: LeaveLockedVideoPage.object.objectType,
1221
+ trackMethod: leaveLockedVideoPageCallback,
1222
+ });
1223
+ }
1224
+ return result;
1225
+ }
1226
+ /**
1227
+ * @param input
1228
+ * @category TPaaS Tracking
1229
+ */
1230
+ async trackViewVideo(input) {
1231
+ // despite the View event type, this is not a page view event, but rather a media object view event
1232
+ // so we shouldn't reset the page view ID here or enable leave tracking
1233
+ const dependencies = await this.prepareTpaasEvent();
1234
+ const event = buildViewVideoEvent(input, dependencies);
1235
+ return this.sendTpaasEvent(event);
1236
+ }
1237
+ /**
1238
+ * Tracks a View VideoPage event and automatically fires a Leave VideoPage event when the user
1239
+ * navigates away.
1240
+ *
1241
+ * The Leave VideoPage event supports an optional `leaveStories` field containing story carousel
1242
+ * statistics that the SDK cannot compute. Provide a `leaveStoriesBuilder` callback in the
1243
+ * `leaveTracking` options — it is called at leave time (not at registration time), so it always
1244
+ * captures the latest state. If no builder is supplied `leaveStories` is omitted from the Leave
1245
+ * VideoPage event.
1246
+ *
1247
+ * `activityDurationMs` and `durationMs` are computed by the leave tracking system and must
1248
+ * **not** be included in the value returned by `leaveStoriesBuilder`.
1249
+ *
1250
+ * @example
1251
+ * ```ts
1252
+ * // Without story stats — leaveStories is omitted from the Leave VideoPage event
1253
+ * await tracker.trackViewVideoPage(input, {
1254
+ * leaveTracking: { objectElement: document.getElementById('video-player')! },
1255
+ * });
1256
+ *
1257
+ * // With leaveStoriesBuilder — capture live story stats at leave time
1258
+ * await tracker.trackViewVideoPage(input, {
1259
+ * leaveTracking: {
1260
+ * objectElement: document.getElementById('video-player')!,
1261
+ * leaveStoriesBuilder: () => ({
1262
+ * storiesCompleted: stories.completed,
1263
+ * storiesStarted: stories.started,
1264
+ * maxPlaylistPosition: stories.maxPosition,
1265
+ * playlistPositionPercentage: stories.positionPercentage,
1266
+ * adCount: stories.adCount,
1267
+ * }),
1268
+ * },
1269
+ * });
1270
+ *
1271
+ * // Disable leave tracking entirely
1272
+ * await tracker.trackViewVideoPage(input, { leaveTracking: false });
1273
+ * ```
1274
+ *
1275
+ * @param input
1276
+ * @param options
1277
+ * @category TPaaS Tracking
1278
+ */
1279
+ async trackViewVideoPage(input, options) {
1280
+ this.newPageView(); // Reset the page view ID if it is not set, to ensure a new page view is tracked
1281
+ this.setCurrentPage(input.object.objectId, 'Video'); // ViewVideoPage.object.type is VideoPage, which is not allowed as a pageType
1282
+ const dependencies = await this.prepareTpaasEvent();
1283
+ const event = buildViewVideoPageEvent(input, dependencies);
1284
+ const result = this.sendTpaasEvent(event);
1285
+ if (shouldEnableLeaveTracking(options.leaveTracking)) {
1286
+ const { objectElement, pageElement, heightBuilder, objectResizable, leaveStoriesBuilder } = options.leaveTracking;
1287
+ const leaveVideoCallback = (leave) => {
1288
+ const leaveStoriesInput = leaveStoriesBuilder?.();
1289
+ this.trackLeaveVideoPage({
1290
+ leave,
1291
+ leaveStories: leaveStoriesInput && {
1292
+ ...leaveStoriesInput,
1293
+ activityDurationMs: leave.activityDurationMs,
1294
+ durationMs: leave.durationMs,
1295
+ },
1296
+ ...input,
1297
+ });
1298
+ };
1299
+ addTpaasLeaveTracking({
1300
+ objectElement,
1301
+ pageElement,
1302
+ heightBuilder,
1303
+ objectResizable,
1304
+ schema: LeaveVideoPage.object.objectType,
1305
+ trackMethod: leaveVideoCallback,
1306
+ });
1307
+ }
1308
+ return result;
1309
+ }
1310
+ /**
1311
+ * @param input
1312
+ * @param options
1313
+ * @category TPaaS Tracking
1314
+ */
1315
+ async trackViewWeather(input, options) {
1316
+ this.newPageView(); // Reset the page view ID if it is not set, to ensure a new page view is tracked
1317
+ this.setCurrentPage(input.object.objectId, 'Page' /* TODO: ViewWeather.object.type once the schema is fixed */);
1318
+ const dependencies = await this.prepareTpaasEvent();
1319
+ const event = buildViewWeatherEvent(input, dependencies);
1320
+ const result = this.sendTpaasEvent(event);
1321
+ if (shouldEnableLeaveTracking(options.leaveTracking)) {
1322
+ const { objectElement, pageElement, heightBuilder, objectResizable } = options.leaveTracking;
1323
+ const leaveWeatherCallback = (leave) => {
1324
+ this.trackLeaveWeather({
1325
+ leave,
1326
+ ...input,
1327
+ });
1328
+ };
1329
+ addTpaasLeaveTracking({
1330
+ objectElement,
1331
+ pageElement,
1332
+ heightBuilder,
1333
+ objectResizable,
1334
+ schema: LeaveWeather.object.objectType,
1335
+ trackMethod: leaveWeatherCallback,
1336
+ });
1337
+ }
1338
+ return result;
1339
+ }
1340
+ /**
1341
+ * @param input
1342
+ * @category TPaaS Tracking
1343
+ */
1344
+ async trackLeaveArticle(input) {
1345
+ const dependencies = await this.prepareTpaasEvent();
1346
+ const event = buildLeaveArticleEvent(input, dependencies);
1347
+ return this.sendTpaasEvent(event);
1348
+ }
1349
+ /**
1350
+ * @param input
1351
+ * @category TPaaS Tracking
1352
+ */
1353
+ async trackLeaveAudioPage(input) {
1354
+ const dependencies = await this.prepareTpaasEvent();
1355
+ const event = buildLeaveAudioPageEvent(input, dependencies);
1356
+ return this.sendTpaasEvent(event);
1357
+ }
1358
+ /**
1359
+ * @param input
1360
+ * @category TPaaS Tracking
1361
+ */
1362
+ async trackLeaveError(input) {
1363
+ const dependencies = await this.prepareTpaasEvent();
1364
+ const event = buildLeaveErrorEvent(input, dependencies);
1365
+ return this.sendTpaasEvent(event);
1366
+ }
1367
+ /**
1368
+ * @param input
1369
+ * @category TPaaS Tracking
1370
+ */
1371
+ async trackLeaveFrontpage(input) {
1372
+ const dependencies = await this.prepareTpaasEvent();
1373
+ const event = buildLeaveFrontpageEvent(input, dependencies);
1374
+ return this.sendTpaasEvent(event);
1375
+ }
1376
+ /**
1377
+ * @param input
1378
+ * @category TPaaS Tracking
1379
+ */
1380
+ async trackLeaveLandingpage(input) {
1381
+ const dependencies = await this.prepareTpaasEvent();
1382
+ const event = buildLeaveLandingpageEvent(input, dependencies);
1383
+ return this.sendTpaasEvent(event);
1384
+ }
1385
+ /**
1386
+ * @param input
1387
+ * @category TPaaS Tracking
1388
+ */
1389
+ async trackLeaveListing(input) {
1390
+ const dependencies = await this.prepareTpaasEvent();
1391
+ const event = buildLeaveListingEvent(input, dependencies);
1392
+ return this.sendTpaasEvent(event);
1393
+ }
1394
+ /**
1395
+ * @param input
1396
+ * @category TPaaS Tracking
1397
+ */
1398
+ async trackLeaveLockedArticle(input) {
1399
+ const dependencies = await this.prepareTpaasEvent();
1400
+ const event = buildLeaveLockedArticleEvent(input, dependencies);
1401
+ return this.sendTpaasEvent(event);
1402
+ }
1403
+ /**
1404
+ * @param input
1405
+ * @category TPaaS Tracking
1406
+ */
1407
+ async trackLeaveLockedAudio(input) {
1408
+ const dependencies = await this.prepareTpaasEvent();
1409
+ const event = buildLeaveLockedAudioEvent(input, dependencies);
1410
+ return this.sendTpaasEvent(event);
1411
+ }
1412
+ /**
1413
+ * @param input
1414
+ * @category TPaaS Tracking
1415
+ */
1416
+ async trackLeaveLockedAudioPage(input) {
1417
+ const dependencies = await this.prepareTpaasEvent();
1418
+ const event = buildLeaveLockedAudioPageEvent(input, dependencies);
1419
+ return this.sendTpaasEvent(event);
1420
+ }
1421
+ /**
1422
+ * @param input
1423
+ * @category TPaaS Tracking
1424
+ */
1425
+ async trackLeaveLockedVideo(input) {
1426
+ const dependencies = await this.prepareTpaasEvent();
1427
+ const event = buildLeaveLockedVideoEvent(input, dependencies);
1428
+ return this.sendTpaasEvent(event);
1429
+ }
1430
+ /**
1431
+ * @param input
1432
+ * @category TPaaS Tracking
1433
+ */
1434
+ async trackLeaveLockedVideoPage(input) {
1435
+ const dependencies = await this.prepareTpaasEvent();
1436
+ const event = buildLeaveLockedVideoPageEvent(input, dependencies);
1437
+ return this.sendTpaasEvent(event);
1438
+ }
1439
+ /**
1440
+ * @param input
1441
+ * @category TPaaS Tracking
1442
+ */
1443
+ async trackLeavePage(input) {
1444
+ const dependencies = await this.prepareTpaasEvent();
1445
+ const event = buildLeavePageEvent(input, dependencies);
1446
+ return this.sendTpaasEvent(event);
1447
+ }
1448
+ /**
1449
+ * @param input
1450
+ * @category TPaaS Tracking
1451
+ */
1452
+ async trackLeaveVideoPage(input) {
1453
+ const dependencies = await this.prepareTpaasEvent();
1454
+ const event = buildLeaveVideoPageEvent(input, dependencies);
1455
+ return this.sendTpaasEvent(event);
1456
+ }
1457
+ /**
1458
+ * @param input
1459
+ * @category TPaaS Tracking
1460
+ */
1461
+ async trackLeaveWeather(input) {
1462
+ const dependencies = await this.prepareTpaasEvent();
1463
+ const event = buildLeaveWeatherEvent(input, dependencies);
1464
+ return this.sendTpaasEvent(event);
1465
+ }
1466
+ /**
1467
+ * @param input
1468
+ * @category TPaaS Tracking
1469
+ */
1470
+ async trackEngagementAudio(input) {
1471
+ const dependencies = await this.prepareTpaasEvent();
1472
+ const event = buildEngagementAudioEvent(input, dependencies);
1473
+ return this.sendTpaasEvent(event);
1474
+ }
1475
+ /**
1476
+ * @param input
1477
+ * @category TPaaS Tracking
1478
+ */
1479
+ async trackEngagementForm(input) {
1480
+ const dependencies = await this.prepareTpaasEvent();
1481
+ const event = buildEngagementFormEvent(input, dependencies);
1482
+ return this.sendTpaasEvent(event);
1483
+ }
1484
+ /**
1485
+ * @param input
1486
+ * @category TPaaS Tracking
1487
+ */
1488
+ async trackEngagementOffer(input) {
1489
+ const dependencies = await this.prepareTpaasEvent();
1490
+ const event = buildEngagementOfferEvent(input, dependencies);
1491
+ return this.sendTpaasEvent(event);
1492
+ }
1493
+ /**
1494
+ * @param input
1495
+ * @category TPaaS Tracking
1496
+ */
1497
+ async trackEngagementTeaser(input) {
1498
+ const dependencies = await this.prepareTpaasEvent();
1499
+ const event = buildEngagementTeaserEvent(input, dependencies);
1500
+ return this.sendTpaasEvent(event);
1501
+ }
1502
+ /**
1503
+ * @param input
1504
+ * @category TPaaS Tracking
1505
+ */
1506
+ async trackEngagementUIElement(input) {
1507
+ const dependencies = await this.prepareTpaasEvent();
1508
+ const event = buildEngagementUIElementEvent(input, dependencies);
1509
+ return this.sendTpaasEvent(event);
1510
+ }
1511
+ /**
1512
+ * @param input
1513
+ * @category TPaaS Tracking
1514
+ */
1515
+ async trackEngagementVideo(input) {
1516
+ const dependencies = await this.prepareTpaasEvent();
1517
+ const event = buildEngagementVideoEvent(input, dependencies);
1518
+ return this.sendTpaasEvent(event);
1519
+ }
1520
+ /**
1521
+ * @param input
1522
+ * @category TPaaS Tracking
1523
+ */
1524
+ async trackEngagementVideoAd(input) {
1525
+ const dependencies = await this.prepareTpaasEvent();
1526
+ const event = buildEngagementVideoAdEvent(input, dependencies);
1527
+ return this.sendTpaasEvent(event);
1528
+ }
1529
+ /**
1530
+ * @param input
1531
+ * @category TPaaS Tracking
1532
+ */
1533
+ async trackEngagementWidget(input) {
1534
+ const dependencies = await this.prepareTpaasEvent();
1535
+ const event = buildEngagementWidgetEvent(input, dependencies);
1536
+ return this.sendTpaasEvent(event);
1537
+ }
1538
+ /**
1539
+ * this is the method that actually sends the event to the server
1540
+ * @private
1541
+ * @category TPaaS Tracking
1542
+ */
1543
+ async sendTpaasEvent(event) {
1544
+ // Resolve any pending session ID promises
1545
+ // (session was created when the event was built)
1546
+ this.resolveSessionIdPromise();
1547
+ // The Hybrid use case implements a "bridged" event method, injected into the window scope,
1548
+ // which is used to send events through the native app.
1549
+ if (isFunction(this.state.altEventHandler)) {
1550
+ this.state.altEventHandler(JSON.stringify(event));
1551
+ return event;
1552
+ }
1553
+ this.tpaasEventQueue.push(event);
1554
+ if (this.state.useBeacon) {
1555
+ try {
1556
+ return await this._sendImmediatelyTpaas();
1557
+ }
1558
+ catch (err) {
1559
+ return err;
1560
+ }
1561
+ }
1562
+ return this.debouncedSendTpaas();
1563
+ }
1564
+ /**
1565
+ * Send all events that are in the internal event queue.
1566
+ *
1567
+ * The returned Promise will resolve with the array of events that was
1568
+ * successfully transmitted. These events will have been removed from the event
1569
+ * queue. If the promise rejects, it means that the event queue could not be
1570
+ * sent and the promise rejection will contain the events that failed (will be
1571
+ * the entire queue initial call). Events that are unsuccessfully sent will
1572
+ * remain in the event queue.
1573
+ *
1574
+ * @internal
1575
+ * @category TPaaS Tracking
1576
+ */
1577
+ async _sendImmediatelyTpaas() {
1578
+ if (this.tpaasEventQueue.length + this.retryTpaasEventQueue.length <= 0) {
1579
+ return [];
1580
+ }
1581
+ return this.prepareQueuesAndSendTpaas(this.tpaasEventQueue, this.retryTpaasEventQueue);
1582
+ }
1583
+ /**
1584
+ * Prepares the received event queue and handles success / failure after sending.
1585
+ *
1586
+ * @param eventQueue
1587
+ * @param retryEventQueue
1588
+ * @private
1589
+ * @category TPaaS Tracking
1590
+ */
1591
+ async prepareQueuesAndSendTpaas(eventQueue, retryEventQueue) {
1592
+ const eventsToBeSent = eventQueue.splice(0);
1593
+ const eventsToRetry = retryEventQueue.splice(0);
1594
+ eventQueue.length = 0;
1595
+ retryEventQueue.length = 0;
1596
+ const url = this._getTpaasCollectorPath();
1597
+ const data = [...eventsToBeSent, ...eventsToRetry];
1598
+ async function onFailedSend() {
1599
+ // We retry an event once, but discard already retried events
1600
+ retryEventQueue.push(...eventsToBeSent);
1601
+ return Promise.reject(eventsToBeSent);
1602
+ }
1603
+ try {
1604
+ // for TPaaS events, we set the sentAt time to the current date, just before sending the events
1605
+ const currentDate = new Date().toISOString();
1606
+ for (const event of data) {
1607
+ event.time.sentAt = currentDate;
1608
+ }
1609
+ const response = await send(url, data, this.state);
1610
+ if (response.status >= 400) {
1611
+ onFailedSend();
1612
+ }
1613
+ return eventsToBeSent;
1614
+ }
1615
+ catch (_ex) {
1616
+ return onFailedSend();
1617
+ }
1618
+ }
1619
+ /**
1620
+ * Evaluate all input given to the sdk/this method and pass it through the
1621
+ * appropriate event formatter.
1622
+ * @internal
1623
+ * @category Legacy Tracking
1624
+ */
1625
+ async evaluateEvent(eventType, input, builders = this.builders, options) {
1626
+ const eventBuilder = getEventBuilder(eventType);
1627
+ return this.evaluateEventInputs(eventType, input, builders, options).then((evaluatedInput) => {
1628
+ const data = eventBuilder({
1629
+ eventInput: evaluatedInput,
1630
+ sdkConfig: this.state,
1631
+ });
1632
+ return evaluateAndFlatten(data);
1633
+ });
1634
+ }
1635
+ /**
1636
+ * @param eventType
1637
+ * @param eventInput
1638
+ * @param builders
1639
+ * @param options
1640
+ * @internal
1641
+ * @category Legacy Tracking
1642
+ */
1643
+ async evaluateEventInputs(eventType, eventInput, builders = this.builders, options) {
1644
+ const buildersOutput = await Promise.all([evaluateAndFlatten(builders), evaluateAndFlatten(eventInput)]);
1645
+ let eventOutput = buildersOutput.reduce((acc, p) => pulseMerge(acc, p), {});
1646
+ eventOutput = this.applyEventTypeDefaults(eventOutput, eventType);
1647
+ eventOutput = this.applyBookmarkedEvent(eventOutput, options?.applyBookmarkKey);
1648
+ eventOutput = await this.applyConsents(eventOutput);
1649
+ return eventOutput;
1650
+ }
1651
+ /**
1652
+ * Gets user consents from the tracker's state.
1653
+ * @returns {Consents}
1654
+ * @category Consents
1655
+ */
1656
+ async getConsents() {
1657
+ return (await this.evaluateConsents()).consents;
1658
+ }
1659
+ /**
1660
+ * Sets user consents to be sent with each event.
1661
+ * Given that User's consent for Advertising changed, the next call to get Advertising Identifiers must be forced, and
1662
+ * not retrieve values from cache. The flag is passed with the trackers state, and updated to a "non-forcing" state
1663
+ * right after, characterising the "force once" behaviour.
1664
+ * accessing Advertising Identifiers directly must clear this flag.
1665
+ * Not usable with autoCreateConsents option
1666
+ * @param consentsInput
1667
+ * @returns {Consents}
1668
+ * @category Consents
1669
+ */
1670
+ setConsents(consentsInput) {
1671
+ if (this.state.autoCreateConsents) {
1672
+ warnOnce('setConsents', 'setConsents is not allowed when autoCreateConsents is enabled');
1673
+ return { ...this.state.consents };
1674
+ }
1675
+ return this.setConsentsInternal(consentsInput);
1676
+ }
1677
+ /**
1678
+ * Return a new Tracker with the current state
1679
+ * @category Tracking
1680
+ */
1681
+ clone({ trackerId } = {}) {
1682
+ return new Tracker(this.state.providerId, {
1683
+ ...this.state,
1684
+ trackerId: trackerId || v4(),
1685
+ }, {
1686
+ ...this.builders,
1687
+ });
1688
+ }
1689
+ /**
1690
+ * Update the persisted state that is passed to all events
1691
+ *
1692
+ * Calling
1693
+ * ```
1694
+ * tracker.update({ actor: 'person@example.org' });
1695
+ * tracker.trackPageView();
1696
+ * tracker.trackPageView();
1697
+ * ```
1698
+ *
1699
+ * is equivalent of doing
1700
+ *
1701
+ * ```
1702
+ * tracker.trackPageView({ actor: 'person@example.org' });
1703
+ * tracker.trackPageView({ actor: 'person@example.org' });
1704
+ * ```
1705
+ *
1706
+ * @param builder data passed to event functions
1707
+ * @param mergeBuilder the given data will be merged deeply with the
1708
+ * existing state. False will result in the previous state being overwritten
1709
+ * @category Legacy Tracking
1710
+ */
1711
+ update(builder, mergeBuilder = false) {
1712
+ if (mergeBuilder) {
1713
+ this.builders = pulseMerge({}, this.builders, builder);
1714
+ }
1715
+ else {
1716
+ this.builders = Object.assign({}, this.builders, builder);
1717
+ }
1718
+ }
1719
+ /**
1720
+ * Get the actor id (userId) from the current browser. A promise is returned
1721
+ * because a call may be made to complete the login process.
1722
+ *
1723
+ * *Note*: This method will return a Promise that is always rejected on node
1724
+ environments.
1725
+ @category Identifiers
1726
+ */
1727
+ async getUserId() {
1728
+ await this._applyRemoteConfigEndpoints();
1729
+ return identity.getUserId(this.builders);
1730
+ }
1731
+ /**
1732
+ * Get the advertisement id (adId) from the current browser. A promise is returned
1733
+ * because a CIS call is done to generate a new adId if no cookie is
1734
+ * found.
1735
+ *
1736
+ * *Note*: This method will return a Promise that is always rejected on node
1737
+ * environments.
1738
+ * @category Identifiers
1739
+ * @deprecated Advertising Identifiers methods will be removed in the next major version.
1740
+ */
1741
+ async getAdId() {
1742
+ warnOnce('getAdId', 'Deprecated method: getAdId');
1743
+ await this._applyRemoteConfigEndpoints();
1744
+ return identity.getAdId(this.builders, this.state);
1745
+ }
1746
+ /**
1747
+ * @category Identifiers
1748
+ * @deprecated moving away from "Actor" terminology, in favor of "User"
1749
+ */
1750
+ async getActor() {
1751
+ await this._applyRemoteConfigEndpoints();
1752
+ return identity.getActor(this.builders);
1753
+ }
1754
+ /**
1755
+ * Get the environment id from the current browser. A promise is returned
1756
+ * because a CIS call is done to generate a new environmentId if no cookie is
1757
+ * found.
1758
+ *
1759
+ * *Note*: This method will return a Promise that is always rejected on node
1760
+ * environments.
1761
+ * @category Identifiers
1762
+ */
1763
+ async getEnvironmentId() {
1764
+ await this._applyRemoteConfigEndpoints();
1765
+ return identity.getEnvironmentId(this.builders, this.state);
1766
+ }
1767
+ /**
1768
+ * Returns the PPID1 value for Xandr integration.
1769
+ * This is the "logged in identifier".
1770
+ * @category Identifiers
1771
+ * @deprecated Advertising Identifiers methods will be removed in the next major version.
1772
+ */
1773
+ async getXandrPPID1() {
1774
+ warnOnce('getXandrPPID1', 'Deprecated method: getXandrPPID1');
1775
+ const { xandr } = await identity.getAdvertisingIdentifiers(this.builders, { ...this.state });
1776
+ return xandr?.ppId1;
1777
+ }
1778
+ /**
1779
+ * Returns the PPID2 value for Xandr integration.
1780
+ * This is the "not logged in identifier".
1781
+ * @category Identifiers
1782
+ * @deprecated Advertising Identifiers methods will be removed in the next major version.
1783
+ */
1784
+ async getXandrPPID2() {
1785
+ warnOnce('getXandrPPID2', 'Deprecated method: getXandrPPID2');
1786
+ const { xandr } = await identity.getAdvertisingIdentifiers(this.builders, { ...this.state });
1787
+ return xandr?.ppId2;
1788
+ }
1789
+ async getAdvertisingIdentifiers(_vendor) {
1790
+ warnOnce('getAdvertisingIdentifiers', 'Deprecated method: getAdvertisingIdentifiers');
1791
+ if (_vendor) {
1792
+ warnOnce('getAdvertisingIdentifiers-no-vendor', 'getAdvertisingIdentifiers no longer accepts vendors as input, the vendors given in SDK constructor is used');
1793
+ }
1794
+ await this._applyRemoteConfigEndpoints();
1795
+ return identity.getAdvertisingIdentifiers(this.builders, { ...this.state });
1796
+ }
1797
+ /**
1798
+ * Returns the UUID currently used as the page view (will be muted by `newPageView` and `trackPageView`).
1799
+ * @category Tracking
1800
+ */
1801
+ getPageViewId() {
1802
+ return this.state.pageViewId;
1803
+ }
1804
+ /**
1805
+ * Returns the current session ID.
1806
+ * If a session exists, returns the session ID immediately.
1807
+ * If no session exists yet, returns a promise that resolves with the session ID
1808
+ * when it gets created (typically when the first non-anonymous tracking event is sent).
1809
+ *
1810
+ * Note: Anonymous events (such as those sent via {@link trackAnonymous} or {@link trackAnonymousViewUIElement})
1811
+ * do not create sessions and will not resolve pending session ID promises. The promise will only resolve when a
1812
+ * non-anonymous tracking event is sent.
1813
+ *
1814
+ * It is possible the promise will never get resolved if there are no non-anonymous events being tracked after calling this method.
1815
+ *
1816
+ * @category Tracking
1817
+ * @returns The session ID, or a promise that resolves to the session ID
1818
+ */
1819
+ getSessionId() {
1820
+ const session = readSession();
1821
+ if (session?.id) {
1822
+ return Promise.resolve(session.id);
1823
+ }
1824
+ // No session exists yet, create or return existing promise
1825
+ if (!this.sessionIdPromise) {
1826
+ this.sessionIdPromise = new Promise((resolve) => {
1827
+ const callback = ({ sessionId }) => {
1828
+ resolve(sessionId);
1829
+ this.sessionIdPromise = null; // reset the promise so that future calls to getSessionId will create a new one if needed
1830
+ eventBus.off('tracker:session:new', callback);
1831
+ };
1832
+ eventBus.on('tracker:session:new', callback);
1833
+ });
1834
+ }
1835
+ return this.sessionIdPromise;
1836
+ }
1837
+ /**
1838
+ * Generate a new page view id. Will be attached to all events until a new id is generated.
1839
+ * @category Tracking
1840
+ */
1841
+ newPageView() {
1842
+ this.state.pageViewId = v4();
1843
+ }
1844
+ /**
1845
+ * Fetches the Remote Configuration, setting the CIS and Collector base urls
1846
+ * @internal
1847
+ * @category Configuration
1848
+ */
1849
+ async _applyRemoteConfigEndpoints() {
1850
+ const { fallbackCisBaseUrl, fallbackCollectorBaseUrl, environment, configurationTag, remoteConfigurationUrl } = this.state;
1851
+ if (environment === 'browser') {
1852
+ const remoteServiceConfig = await config.syncRemoteConfig(configurationTag, remoteConfigurationUrl);
1853
+ if (!isCollectorInConfig) {
1854
+ this.state.collectorBaseUrl = remoteServiceConfig?.collector || fallbackCollectorBaseUrl;
1855
+ }
1856
+ if (!isCisInConfig) {
1857
+ this.state.cisBaseUrl = remoteServiceConfig?.cis || fallbackCisBaseUrl;
1858
+ }
1859
+ }
1860
+ }
1861
+ /**
1862
+ * @param input
1863
+ * @param builders
1864
+ * @internal
1865
+ * @category Configuration
1866
+ */
1867
+ async syncRemoteResources(input, builders) {
1868
+ await this._applyRemoteConfigEndpoints();
1869
+ return identity.cisSync(input, builders, { ...this.state });
1870
+ }
1871
+ /**
1872
+ * @internal
1873
+ * @category Configuration
1874
+ */
1875
+ _getCollectorPath() {
1876
+ const { providerId, environment } = this.state;
1877
+ let { collectorPath, collectorBaseUrl } = this.state;
1878
+ /**
1879
+ * We want to support all of these cases:
1880
+ * collectorPath: /api/v1/track, baseUrl: domain.tld => domain.tld/api/v1/track
1881
+ * collectorPath: api/v1/track, baseUrl: domain.tld => domain.tld/api/v1/track
1882
+ * collectorPath: /api/v1/track, baseUrl: domain.tld/ => domain.tld/api/v1/track
1883
+ * collectorPath: api/v1/track, baseUrl: domain.tld/ => domain.tld/api/v1/track
1884
+ * collectorPath: /api/v1/track, baseUrl: domain.tld/something => domain.tld/something/api/v1/track
1885
+ * collectorPath: api/v1/track, baseUrl: domain.tld/something => domain.tld/something/api/v1/track
1886
+ * collectorPath: /api/v1/track, baseUrl: domain.tld/something/ => domain.tld/something/api/v1/track
1887
+ * collectorPath: api/v1/track, baseUrl: domain.tld/something/ => domain.tld/something/api/v1/track
1888
+ * The collectorPath and collectorBaseUrl manipulating below is to support all these cases
1889
+ */
1890
+ if (collectorPath.startsWith('/')) {
1891
+ // Remove leading slash
1892
+ collectorPath = collectorPath.slice(1);
1893
+ }
1894
+ if (!collectorBaseUrl?.endsWith('/')) {
1895
+ // Add trailing slash
1896
+ collectorBaseUrl = `${collectorBaseUrl}/`;
1897
+ }
1898
+ if (environment === 'node') {
1899
+ return new URL(collectorPath, collectorBaseUrl).toString();
1900
+ }
1901
+ const _provider = providerId || this.state.providerId;
1902
+ if (typeof _provider === 'string' && _provider.indexOf('sdrn') === 0) {
1903
+ return new URL(`${collectorPath}/${_provider}`, collectorBaseUrl).toString();
1904
+ }
1905
+ return new URL(`${collectorPath}/${providerSdrn(_provider)}`, collectorBaseUrl).toString();
1906
+ }
1907
+ /**
1908
+ * Returns the collector URL for TPaaS events.
1909
+ * Uses the tpaasCollectorBaseUrl when available (driven by deployStageTpaas),
1910
+ *
1911
+ * @internal
1912
+ * @category Configuration
1913
+ */
1914
+ _getTpaasCollectorPath() {
1915
+ const { providerId } = this.state;
1916
+ let { collectorPath, tpaasCollectorBaseUrl } = this.state;
1917
+ if (collectorPath.startsWith('/')) {
1918
+ // Remove leading slash
1919
+ collectorPath = collectorPath.slice(1);
1920
+ }
1921
+ if (!tpaasCollectorBaseUrl.endsWith('/')) {
1922
+ // Add trailing slash
1923
+ tpaasCollectorBaseUrl = `${tpaasCollectorBaseUrl}/`;
1924
+ }
1925
+ if (typeof providerId === 'string' && providerId.indexOf('sdrn') === 0) {
1926
+ return new URL(`${collectorPath}/${providerId}`, tpaasCollectorBaseUrl).toString();
1927
+ }
1928
+ return new URL(`${collectorPath}/${providerSdrn(providerId)}`, tpaasCollectorBaseUrl).toString();
1929
+ }
1930
+ /**
1931
+ * Send all events that are in the internal event queue.
1932
+ *
1933
+ * The returned Promise will resolve with the array of events that was
1934
+ * successfully transmitted. These events will have been removed from the event
1935
+ * queue. If the promise rejects, it means that the event queue could not be
1936
+ * sent and the promise rejection will contain the events that failed (will be
1937
+ * the entire queue initial call). Events that are unsuccessfully sent will
1938
+ * remain in the event queue.
1939
+ *
1940
+ * @internal
1941
+ * @category Legacy Tracking
1942
+ *
1943
+ */
1944
+ async _sendImmediately() {
1945
+ if (this.eventQueue.length + this.retryEventQueue.length <= 0) {
1946
+ return [];
1947
+ }
1948
+ const { doTracking } = await identity.cisSync({}, this.builders, this.state);
1949
+ if (!doTracking) {
1950
+ return [];
1951
+ }
1952
+ return this.prepareQueuesAndSend(this.eventQueue, this.retryEventQueue);
1953
+ }
1954
+ /**
1955
+ * @param event
1956
+ * @param options
1957
+ * @internal
1958
+ * @category Legacy Tracking
1959
+ */
1960
+ _push(event, options = {}) {
1961
+ const deferredEvent = defer(event);
1962
+ this.eventQueue.push(deferredEvent);
1963
+ if (options.resolveOnQueued) {
1964
+ deferredEvent.resolve(event);
1965
+ }
1966
+ return deferredEvent.promise;
1967
+ }
1968
+ /**
1969
+ * @param bookmarkKey
1970
+ * @internal
1971
+ * @category Legacy Tracking
1972
+ */
1973
+ getBookmarkedEvent(bookmarkKey) {
1974
+ return this.bookmark.get(bookmarkKey);
1975
+ }
1976
+ /**
1977
+ * Send the current event queue to the back end event receiver. This event is
1978
+ * debounced, @see {SDKConfigInput} to override the default timing.
1979
+ *
1980
+ * This method is called by `track()` so it is not necessary to call after
1981
+ * adding events to the queue.
1982
+ * @internal
1983
+ * @category Legacy Tracking
1984
+ */
1985
+ async send() {
1986
+ if (this.state.useBeacon) {
1987
+ try {
1988
+ return await this._sendImmediately();
1989
+ }
1990
+ catch (err) {
1991
+ return err;
1992
+ }
1993
+ }
1994
+ return this.debouncedSend();
1995
+ }
1996
+ /**
1997
+ * A convenience method which first updates the current pageViewId in the
1998
+ * tracker state and then sends a `tracker-event` with `@type: View` and the
1999
+ * merged result of the given data and the data saved in the tracker.
2000
+ *
2001
+ * Equivalent to
2002
+ *
2003
+ * ```ts
2004
+ * tracker.newPageView();
2005
+ * tracker.track('trackerEvent', { type: 'View', ...data });
2006
+ * ```
2007
+ * @category Legacy Tracking
2008
+ */
2009
+ trackPageView(data = {}, options = {}) {
2010
+ this.newPageView();
2011
+ return this.track('trackerEvent', { type: 'View', ...data }, { ...options, bookmarkKey: BookmarkKeys.PAGE_VIEW });
2012
+ }
2013
+ /**
2014
+ * Start sending events when users leave a page.
2015
+ * This will register handlers on the browser events 'pagehide', 'popstate', 'beforeunload' and 'visibilitychange'
2016
+ * and will send a Leave event when these are triggered. The leave event will be a copy of the last sent view-event
2017
+ * + engagement values. The fields in the default
2018
+ * event can be found here: https://pages.github.schibsted.io/mpt-data/pulse-standard/#leave-article.
2019
+ * The Leave event can be expanded further by passing an event-builder as the third param, but this is not recommended.
2020
+ *
2021
+ * Example usage:
2022
+ *
2023
+ * ```ts
2024
+ * const pageElement = document.querySelector('#application') || document.body;
2025
+ * const articleElement = document.getElementById('article-element');
2026
+ * tracker.addPageLeaveTracking(articleElement, pageElement);
2027
+ * ```
2028
+ *
2029
+ * Passing '\{ objectResizable: true \}' as the 4th param makes the SDK re-calculate the object height whenever it changes,
2030
+ * which is useful for when the page or object changes size after loading, by ex
2031
+ * ```
2032
+ * ...
2033
+ * tracker.addPageLeaveTracking(articleElement, pageElement, undefined, {
2034
+ * objectResizable: true,
2035
+ * });
2036
+ * ```
2037
+ *
2038
+ * Keep in mind that the Beacon API is used to send events to page leave, and in order to guarantee as good as
2039
+ * possible that these events are sent, the event creator parameter should be synchronous.
2040
+ *
2041
+ * For the same reasons, we advise that the event creator parameter returns an event that does not contain any promises.
2042
+ *
2043
+ * @param {Element} objectElement The DOM element that is used to calculate various view-related fields in the default event.
2044
+ * @param {Element} pageElement The DOM element that represents the page that the user is currently on.
2045
+ * @param {LeaveEventBuilder} eventBuilder Function that returns an event to send when user leaves the page.
2046
+ * @param {LeaveEventOptions} options
2047
+ * @returns {(leaveEvent: LeaveEvent) => void} A function to update the event to send on page leave.
2048
+ * @category Leave Event
2049
+ */
2050
+ addPageLeaveTracking(objectElement, pageElement, eventBuilder, options = {}) {
2051
+ addPageLeaveTracking(this, objectElement, pageElement, eventBuilder, options);
2052
+ return updatePageLeaveEvent;
2053
+ }
2054
+ /**
2055
+ * Stop sending events when users leave a page.
2056
+ * Removes all event handlers, meaning that to event will be sent if the user leaves the page.
2057
+ * @category Leave Event
2058
+ */
2059
+ removePageLeaveTracking() {
2060
+ removePageLeaveTracking(this);
2061
+ }
2062
+ /**
2063
+ * Update leave tracking.
2064
+ * Updates the DOM element used to calculate the default fields in the Leave event.
2065
+ * @param objectElement The DOM element that is used to calculate various view-related fields in the default event.
2066
+ * @param pageElement The DOM element that represents the page that the user is currently on.
2067
+ * @param resetProperties A flag that decided whether the engagement properties of the Leave event should
2068
+ * be reset when the tracking is updated. Defaults to false.
2069
+ * @category Leave Event
2070
+ */
2071
+ updatePageLeaveTracking(objectElement, pageElement, resetProperties = false) {
2072
+ updatePageLeaveTracking(objectElement, pageElement, resetProperties);
2073
+ }
2074
+ /**
2075
+ * Manually trigger a viewed content recalculation including resetting max-values
2076
+ * @param objectElement The DOM element that is used to calculate various view-related fields in the
2077
+ * default event.
2078
+ * @param pageElement The DOM element that represents the page that the user is currently on.
2079
+ * @category Leave Event
2080
+ */
2081
+ resetPageLeaveViewedContent(objectElement, pageElement) {
2082
+ resetViewedContent();
2083
+ updateViewedContent(objectElement, pageElement);
2084
+ }
2085
+ /**
2086
+ * Manually trigger a viewed content recalculation without resetting max-values
2087
+ * @param objectElement The DOM element that is used to calculate various view-related fields in the
2088
+ * default event.
2089
+ * @param pageElement The DOM element that represents the page that the user is currently on.
2090
+ * @category Leave Event
2091
+ */
2092
+ updatePageLeaveViewedContent(objectElement, pageElement) {
2093
+ updateViewedContent(objectElement, pageElement);
2094
+ }
2095
+ /**
2096
+ * Manually trigger a Leave event
2097
+ * Useful if for example the consuming website is an SPA and the normal browser events are not triggered.
2098
+ * is generated internally in the SDK.
2099
+ * @param eventInput
2100
+ * @param eventName The optional name of the browser event to simulate.
2101
+ * @category Leave Event
2102
+ */
2103
+ async trackPageLeave(eventInput, eventName) {
2104
+ await trackPageLeave(this, eventInput, eventName);
2105
+ }
2106
+ /**
2107
+ * Manually trigger a Leave event only if Page Leave tracking is active in the SDK
2108
+ * This method works similarly to
2109
+ * ```
2110
+ * trackPageLeave(event: LeaveEvent, eventName?: string)
2111
+ * ```
2112
+ * with the added guarantee that a second Leave event will not be triggered if one already has been sent.
2113
+ * is generated internally in the SDK.
2114
+ * @param eventInput
2115
+ * @param eventName The optional name of the browser event to simulate.
2116
+ * @category Leave Event
2117
+ */
2118
+ trackActivePageLeave(eventInput, eventName) {
2119
+ trackActivePageLeave(this, eventInput, eventName);
2120
+ }
2121
+ /**
2122
+ * Check if leave tracking is enabled (if an event will be sent when the user leaves the page)
2123
+ * ```
2124
+ * isLeaveTrackingActive()
2125
+ * ```
2126
+ * @category Leave Event
2127
+ */
2128
+ isLeaveTrackingActive() {
2129
+ return leaveTrackingIsActive();
2130
+ }
2131
+ /**
2132
+ * Update leave tracking.
2133
+ * Updates the DOM element used to calculate the default fields in the Leave event.
2134
+ * @param {Element} objectElement The DOM element that is used to calculate various view-related fields in the default event.
2135
+ * @param {Element} pageElement The DOM element that represents the page that the user is currently on.
2136
+ * @param {boolean} resetProperties A flag that decided whether the engagement properties of the Leave event should
2137
+ * be reset when the tracking is updated. Defaults to false.
2138
+ * @category TPaaS Leave Tracking
2139
+ */
2140
+ updateTpaasLeaveTracking(objectElement, pageElement, resetProperties = false) {
2141
+ updateTpaasLeaveTracking(objectElement, pageElement, resetProperties);
2142
+ }
2143
+ /**
2144
+ * Manually trigger a viewed content recalculation including resetting max-values
2145
+ * @param {Element} objectElement The DOM element that is used to calculate various view-related fields in the
2146
+ * default event.
2147
+ * @param {Element} pageElement The DOM element that represents the page that the user is currently on.
2148
+ * @category TPaaS Leave Tracking
2149
+ */
2150
+ resetTpaasLeaveViewedContent(objectElement, pageElement) {
2151
+ resetTpaasViewedContent();
2152
+ updateTpaasViewedContent(objectElement, pageElement);
2153
+ }
2154
+ /**
2155
+ * Manually trigger a viewed content recalculation without resetting max-values
2156
+ * @param {Element} objectElement The DOM element that is used to calculate various view-related fields in the
2157
+ * default event.
2158
+ * @param {Element} pageElement The DOM element that represents the page that the user is currently on.
2159
+ * @category TPaaS Leave Tracking
2160
+ */
2161
+ updateTpaasLeaveViewedContent(objectElement, pageElement) {
2162
+ updateTpaasViewedContent(objectElement, pageElement);
2163
+ }
2164
+ /**
2165
+ * Get the current Leave object. Useful to fetch before manually sending a leave event using one of the trackLeaveX TPaaS methods.
2166
+ * @returns {ILeave} The current Leave event object.
2167
+ * @category TPaaS Leave Tracking
2168
+ */
2169
+ getTpaasLeaveObject() {
2170
+ return getTpaasLeaveObject();
2171
+ }
2172
+ /**
2173
+ * Manually trigger a Leave event only if Page Leave tracking is active in the SDK
2174
+ * This method works similarly to the track TPaaS methods trackLeaveX
2175
+ * ```
2176
+ * trackLeavePage(input: InputParams<ILeavePage>)
2177
+ * ```
2178
+ * with the added guarantee that a second Leave event will not be triggered if one already has been sent.
2179
+ * @category TPaaS Leave Tracking
2180
+ */
2181
+ trackTpaasActiveLeave() {
2182
+ trackTpaasActiveLeave();
2183
+ }
2184
+ /**
2185
+ * Check if leave tracking is enabled (if an event will be sent when the user leaves the page)
2186
+ * ```
2187
+ * isLeaveTpaasTrackingActive()
2188
+ * ```
2189
+ * @category TPaaS Leave Tracking
2190
+ */
2191
+ isLeaveTpaasTrackingActive() {
2192
+ return leaveTpaasTrackingIsActive();
2193
+ }
2194
+ /**
2195
+ * Start listening for events from the Tracker Proxy clients.
2196
+ * @returns teardown function that stops the listener
2197
+ */
2198
+ exposeToProxyClients() {
2199
+ return startProxyProviderListener(this);
2200
+ }
2201
+ /**
2202
+ * @param input
2203
+ * @private
2204
+ */
2205
+ async resolveTrackInput(input) {
2206
+ return evaluateAndFlatten(input);
2207
+ }
2208
+ /**
2209
+ * @private
2210
+ */
2211
+ async resolveTrackGlobals() {
2212
+ return evaluateAndFlatten({ ...this.builders });
2213
+ }
2214
+ /**
2215
+ * Send all anonymous events that are in the internal anonymous event queue.
2216
+ *
2217
+ * The returned Promise will resolve with the array of anonymous events that was
2218
+ * successfully transmitted. These anonymous events will have been removed from the anonymous event
2219
+ * queue. If the promise rejects, it means that the anonymous event queue could not be
2220
+ * sent and the promise rejection will contain the anonymous events that failed.
2221
+ * Anonymous events that are unsuccessfully sent will remain in the anonymous event queue.
2222
+ *
2223
+ * @internal
2224
+ *
2225
+ */
2226
+ async _sendImmediatelyAnonymous() {
2227
+ if (this.anonymousEventQueue.length + this.retryAnonymousEventQueue.length <= 0) {
2228
+ return [];
2229
+ }
2230
+ // Anonymous events are sent without any user identifiers, independently of CIS, so no waiting for CIS sync here
2231
+ return this.prepareQueuesAndSend(this.anonymousEventQueue, this.retryAnonymousEventQueue);
2232
+ }
2233
+ /**
2234
+ * @param event
2235
+ * @param options
2236
+ * @internal
2237
+ */
2238
+ _pushAnonymous(event, options = {}) {
2239
+ const deferredEvent = defer(event);
2240
+ this.anonymousEventQueue.push(deferredEvent);
2241
+ if (options.resolveOnQueued) {
2242
+ deferredEvent.resolve(event);
2243
+ }
2244
+ return deferredEvent.promise;
2245
+ }
2246
+ /**
2247
+ * Send the current anonymous event queue to the back end event receiver. This event is
2248
+ * debounced, @see {SDKConfigInput} to override the default timing.
2249
+ *
2250
+ * This method is called by `trackAnonymous()` so it is not necessary to call after
2251
+ * adding events to the queue.
2252
+ *
2253
+ * @internal
2254
+ */
2255
+ async sendAnonymous() {
2256
+ if (this.state.useBeacon) {
2257
+ try {
2258
+ return await this._sendImmediatelyAnonymous();
2259
+ }
2260
+ catch (err) {
2261
+ return err;
2262
+ }
2263
+ }
2264
+ return this.debouncedSendAnonymous();
2265
+ }
2266
+ /**
2267
+ * Prepares the received event queue and handles success / failure after sending.
2268
+ *
2269
+ * @param eventQueue
2270
+ * @param retryEventQueue
2271
+ * @private
2272
+ */
2273
+ async prepareQueuesAndSend(eventQueue, retryEventQueue) {
2274
+ const promisesToBeSent = eventQueue.splice(0);
2275
+ const eventsToBeSent = promisesToBeSent.map((p) => p.inputValue);
2276
+ const eventsToRetry = retryEventQueue;
2277
+ eventQueue.length = 0;
2278
+ retryEventQueue.length = 0;
2279
+ const evaluatedEvents = await Promise.all(eventsToBeSent);
2280
+ const url = this._getCollectorPath();
2281
+ const data = [...evaluatedEvents, ...eventsToRetry];
2282
+ // biome-ignore lint/suspicious/noExplicitAny: -
2283
+ async function onFailedSend(response) {
2284
+ // We retry an event once, but discard already retried events
2285
+ retryEventQueue.push(...evaluatedEvents);
2286
+ for (const promise of promisesToBeSent) {
2287
+ promise.reject(response);
2288
+ }
2289
+ return Promise.reject(evaluatedEvents);
2290
+ }
2291
+ try {
2292
+ const response = await send(url, data, this.state);
2293
+ if (response.status >= 400) {
2294
+ return onFailedSend(response);
2295
+ }
2296
+ for (const promise of promisesToBeSent) {
2297
+ promise.resolve(response);
2298
+ }
2299
+ return evaluatedEvents;
2300
+ }
2301
+ catch (error) {
2302
+ return onFailedSend(error);
2303
+ }
2304
+ }
2305
+ /**
2306
+ * Creates a new event with values that are global to all event types, and are resolved internally by the sdk.
2307
+ * `creationDate` and `session` are defined as early as possible in the event lifecycle, ensuring they are aligned
2308
+ * and consistent across all events.
2309
+ *
2310
+ * @category Tracker
2311
+ * @private
2312
+ */
2313
+ createEvent(eventInput) {
2314
+ const creationDate = new Date();
2315
+ const session = sessionBuilder({}, creationDate);
2316
+ // Resolve any pending session ID promises
2317
+ this.resolveSessionIdPromise();
2318
+ return pulseMerge({}, eventInput, {
2319
+ '@id': v4(),
2320
+ creationDate: creationDate.toISOString(),
2321
+ session,
2322
+ });
2323
+ }
2324
+ /**
2325
+ * Helper method to resolve any pending session ID promise
2326
+ * @private
2327
+ */
2328
+ resolveSessionIdPromise() {
2329
+ const session = readSession();
2330
+ if (session?.id) {
2331
+ eventBus.emit('tracker:session:new', {
2332
+ sessionId: session.id,
2333
+ });
2334
+ }
2335
+ }
2336
+ /**
2337
+ * Creates a new anonymous event with values that are global to all event types, and are resolved internally by the sdk.
2338
+ * `creationDate` is defined as early as possible in the event lifecycle, ensuring it is aligned and consistent across all events.
2339
+ *
2340
+ * Note: anonymous events do not have a `session` object.
2341
+ *
2342
+ * @category Tracker
2343
+ * @private
2344
+ */
2345
+ createAnonymousEvent(eventInput) {
2346
+ const creationDate = new Date();
2347
+ return pulseMerge({}, eventInput, {
2348
+ '@id': v4(),
2349
+ creationDate: creationDate.toISOString(),
2350
+ });
2351
+ }
2352
+ /**
2353
+ * applyEventTypeDefaults
2354
+ * @param eventInput
2355
+ * @param eventType
2356
+ * @private
2357
+ */
2358
+ applyEventTypeDefaults(eventInput, eventType) {
2359
+ const eventDefaults = getEventBuilder(eventType).defaults;
2360
+ return pulseMerge({}, eventDefaults(), eventInput);
2361
+ }
2362
+ /**
2363
+ * @param eventInput
2364
+ * @param eventType
2365
+ * @private
2366
+ */
2367
+ applyAnonymousEventTypeDefaults(eventInput, eventType) {
2368
+ const eventDefaults = getAnonymousEventBuilder(eventType).defaults;
2369
+ return pulseMerge({}, eventDefaults(), eventInput);
2370
+ }
2371
+ /**
2372
+ * applyBookmarkedEvent
2373
+ * @param eventInput
2374
+ * @param bookmarkKey
2375
+ * @private
2376
+ */
2377
+ applyBookmarkedEvent(eventInput, bookmarkKey) {
2378
+ if (!bookmarkKey) {
2379
+ return eventInput;
2380
+ }
2381
+ const eventOutput = Object.assign({}, eventInput);
2382
+ const bookmarkedPageViewEvent = this.bookmark.get(bookmarkKey) ?? {};
2383
+ const { '@id': _id, '@type': _type, creationDate: _creationDate, ...coreEvent } = bookmarkedPageViewEvent;
2384
+ return pulseMerge({}, eventOutput, coreEvent);
2385
+ }
2386
+ /**
2387
+ * applyConsents
2388
+ * @param eventInput
2389
+ * @private
2390
+ */
2391
+ async applyConsents(eventInput) {
2392
+ return pulseMerge({}, eventInput, await this.evaluateConsents());
2393
+ }
2394
+ /**
2395
+ * applyConsentsAnonymous
2396
+ * @param eventInput
2397
+ * @private
2398
+ */
2399
+ applyConsentsAnonymous(eventInput) {
2400
+ return pulseMerge({}, eventInput, this.evaluateConsentsAnonymous());
2401
+ }
2402
+ /**
2403
+ * Enriches the event with consent data saved in state.
2404
+ * @private
2405
+ * @category Consents
2406
+ */
2407
+ async evaluateConsents() {
2408
+ const consents = await this.state.consents;
2409
+ this.state.consents = consents; // replace state consents with resolved value; helps anonymous tracking, because that doesn't await consent promises
2410
+ return {
2411
+ ...(consents && { consents }),
2412
+ };
2413
+ }
2414
+ /**
2415
+ * Enriches the anonymous event with consent data saved in state.
2416
+ *
2417
+ * If the consents are a promise, it will return a fallback consent object, instead of waiting for consents to resolve
2418
+ * @private
2419
+ * @category Consents
2420
+ */
2421
+ evaluateConsentsAnonymous() {
2422
+ const consents = isPromise(this.state.consents) ? getFallbackConsents() : this.state.consents;
2423
+ return {
2424
+ ...(consents && { consents }),
2425
+ };
2426
+ }
2427
+ /**
2428
+ * Private version of {@link setConsents} that works with autoCreateConsents
2429
+ * @param consentsInput
2430
+ * @private
2431
+ * @category Consents
2432
+ */
2433
+ setConsentsInternal(consentsInput) {
2434
+ const currentIncludeAdvertising = this.state.includeAdvertising;
2435
+ const updatedIncludeAdvertising = applyAdvertisingConsentSync(consentsInput, this.state.requireAdvertisingOptIn);
2436
+ this.state.includeAdvertising = updatedIncludeAdvertising;
2437
+ this.state.consents = consentsInput;
2438
+ // Only require a CIS sync if the user has changed their advertising consent
2439
+ if (currentIncludeAdvertising !== updatedIncludeAdvertising) {
2440
+ identity.requireCisSyncCallForAdvertisingIds();
2441
+ }
2442
+ logger.debug('Consents set', consentsInput);
2443
+ return { ...this.state.consents };
2444
+ }
2445
+ /**
2446
+ * Get the includeAdvertising flag, set on initialisation.
2447
+ * @see constructor
2448
+ * @private
2449
+ * @category Identifiers
2450
+ */
2451
+ async getIncludeAdvertising() {
2452
+ await this._applyRemoteConfigEndpoints();
2453
+ return identity.getIncludeAdvertising(this.state);
2454
+ }
2455
+ }