@playpilot/tpi 8.7.2 → 8.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@playpilot/tpi",
3
- "version": "8.7.2",
3
+ "version": "8.8.0",
4
4
  "type": "module",
5
5
  "scripts": {
6
6
  "dev": "vite dev",
@@ -85,3 +85,8 @@ export const MetaEvent = {
85
85
  SearchQuery: 'SearchQuery',
86
86
  GenreInterest: 'GenreInterest',
87
87
  } as const
88
+
89
+ export const MetaSource = {
90
+ Card: 'tpi_card',
91
+ Link: 'tpi_link',
92
+ }
@@ -189,6 +189,7 @@ export function injectLinksInDocument(elements: HTMLElement[], injections: LinkI
189
189
  duplicate,
190
190
  failed,
191
191
  failed_message: failedMessage,
192
+ matchingElement,
192
193
  }
193
194
  })
194
195
  }
@@ -0,0 +1,6 @@
1
+ import { hasConsentedTo } from './consent'
2
+
3
+ export function isPixelAllowed(): boolean {
4
+ if (!window.PlayPilotLinkInjections.config?.allow_retargeting_pixels) return false
5
+ return hasConsentedTo('pixels')
6
+ }
@@ -103,8 +103,3 @@ export function fireQueuedTrackingEvents(): void {
103
103
 
104
104
  window.PlayPilotLinkInjections.queued_tracking_events = []
105
105
  }
106
-
107
- export function isPixelAllowed(): boolean {
108
- if (!window.PlayPilotLinkInjections.config?.allow_retargeting_pixels) return false
109
- return hasConsentedTo('pixels')
110
- }
@@ -18,6 +18,7 @@ export type LinkInjection = {
18
18
  manual?: boolean
19
19
  removed?: boolean
20
20
  duplicate?: boolean
21
+ matchingElement?: null | Element
21
22
  }
22
23
 
23
24
  export type LinkInjectionRanges = Record<string, { elementIndex: number, from: number, to: number }>
@@ -20,6 +20,7 @@
20
20
  import Debugger from './components/Debugger.svelte'
21
21
  import UserJourney from './components/UserJourney.svelte'
22
22
  import PostersScrollReveal from './components/PostersScrollReveal.svelte'
23
+ import TrackingPixelsForTitleDataPerLink from './components/TrackingPixelsForTitleDataPerLink.svelte'
23
24
 
24
25
  let elements: HTMLElement[] = $state([])
25
26
 
@@ -230,6 +231,10 @@
230
231
  <TrackingPixels pixels={response.pixels} />
231
232
  {/if}
232
233
 
234
+ {#if linkInjections.length}
235
+ <TrackingPixelsForTitleDataPerLink {linkInjections} />
236
+ {/if}
237
+
233
238
  {#key linkInjections}
234
239
  <UserJourney />
235
240
  <PostersScrollReveal />
@@ -106,4 +106,8 @@
106
106
  margin-top: margin(0.5);
107
107
  }
108
108
  }
109
+
110
+ .sorting {
111
+ margin-top: margin(0.1);
112
+ }
109
113
  </style>
@@ -1,8 +1,8 @@
1
1
  <script lang="ts">
2
2
  import genreData from '$lib/data/genres.json'
3
- import { MetaEvent } from '$lib/enums/TrackingEvent'
3
+ import { MetaEvent, MetaSource } from '$lib/enums/TrackingEvent'
4
4
  import { t } from '$lib/localization'
5
- import { isPixelAllowed } from '$lib/tracking'
5
+ import { isPixelAllowed } from '$lib/pixel'
6
6
  import { trackViewViaPixel } from '@playpilot/retargeting-tracking'
7
7
 
8
8
  interface Props {
@@ -20,7 +20,7 @@
20
20
  {@const genreName = genreData.find(g => g.slug === genre)?.name}
21
21
 
22
22
  {#if genreName}
23
- <div class="genre" {@attach isPixelAllowed() ? trackViewViaPixel(MetaEvent.GenreInterest, { genre: genreName }) : null}>
23
+ <div class="genre" {@attach isPixelAllowed() ? trackViewViaPixel(MetaEvent.GenreInterest, { genre: genreName, source: MetaSource.Card }) : null}>
24
24
  {t(genreName)}
25
25
  </div>
26
26
  {/if}
@@ -6,8 +6,8 @@
6
6
  import { t } from '$lib/localization'
7
7
  import type { PlaylinkData } from '$lib/types/playlink'
8
8
  import { trackClickViaPixel, trackViewViaPixel } from '@playpilot/retargeting-tracking'
9
- import { MetaEvent } from '$lib/enums/TrackingEvent'
10
- import { isPixelAllowed } from '$lib/tracking'
9
+ import { MetaEvent, MetaSource } from '$lib/enums/TrackingEvent'
10
+ import { isPixelAllowed } from '$lib/pixel'
11
11
 
12
12
  interface Props {
13
13
  playlink: PlaylinkData
@@ -37,7 +37,7 @@
37
37
  <svelte:element
38
38
  {onclick}
39
39
  this={!window.PlayPilotLinkInjections?.config?.require_affiliate_consent || hasConsentedTo('affiliate') ? 'a' : 'span'}
40
- {@attach usePixel ? trackViewViaPixel(MetaEvent.ProviderInterest, { provider: playlink.slug }) : null}
40
+ {@attach usePixel ? trackViewViaPixel(MetaEvent.ProviderInterest, { provider: playlink.slug, source: MetaSource.Card }) : null}
41
41
  {@attach usePixel ? trackClickViaPixel(MetaEvent.ProviderClick, { provider: playlink.slug }) : null}
42
42
  href={url}
43
43
  target="_blank"
@@ -0,0 +1,61 @@
1
+ <script lang="ts">
2
+ import genreData from '$lib/data/genres.json'
3
+ import { MetaEvent, MetaSource } from '$lib/enums/TrackingEvent'
4
+ import { keyDataAttribute } from '$lib/injection'
5
+ import { isPixelAllowed } from '$lib/pixel'
6
+ import type { LinkInjection } from '$lib/types/injection'
7
+ import type { TitleData } from '$lib/types/title'
8
+ import { trackViaPixel } from '@playpilot/retargeting-tracking'
9
+ import { onMount } from 'svelte'
10
+
11
+ interface Props {
12
+ linkInjections: LinkInjection[]
13
+ }
14
+
15
+ const { linkInjections }: Props = $props()
16
+
17
+ const previouslyTrackingTitles: string[] = []
18
+
19
+ onMount(() => {
20
+ if (!isPixelAllowed()) return
21
+
22
+ const observer = new IntersectionObserver((entries) => {
23
+ entries.forEach(entry => {
24
+ if (!entry.isIntersecting) return
25
+
26
+ observer!.unobserve(entry.target)
27
+
28
+ const key = entry.target.getAttribute(keyDataAttribute)
29
+ const matchingInjection = linkInjections.find(injection => injection.key === key)
30
+ const title = matchingInjection?.title_details
31
+
32
+ if (!key || !matchingInjection || !title) return
33
+ if (previouslyTrackingTitles.includes(title.sid)) return
34
+
35
+ trackPixelsForTitle(title)
36
+ })
37
+ })
38
+
39
+ linkInjections.forEach(injection => {
40
+ if (injection.matchingElement) observer.observe(injection.matchingElement)
41
+ })
42
+
43
+ return () => observer.disconnect()
44
+ })
45
+
46
+ function trackPixelsForTitle({ sid, genres, participants, providers }: TitleData): void {
47
+ previouslyTrackingTitles.push(sid)
48
+
49
+ genres.slice(0, 3).forEach(genre => {
50
+ trackViaPixel(MetaEvent.GenreInterest, { genre: genreData.find(g => g.slug === genre)?.name, source: MetaSource.Link })
51
+ })
52
+
53
+ participants?.slice(0, 5).forEach(participant => {
54
+ trackViaPixel(MetaEvent.ParticipantInterest, { participant: participant.name, source: MetaSource.Link })
55
+ })
56
+
57
+ providers?.forEach(provider => {
58
+ trackViaPixel(MetaEvent.ProviderInterest, { provider: provider.name, source: MetaSource.Link })
59
+ })
60
+ }
61
+ </script>
@@ -28,7 +28,7 @@
28
28
 
29
29
  observeCreatedLinks()
30
30
 
31
- ;() => linksIntersectionObserver?.disconnect()
31
+ return () => linksIntersectionObserver?.disconnect?.()
32
32
  })
33
33
 
34
34
  function observeCreatedLinks(): void {
@@ -0,0 +1,53 @@
1
+ import { hasConsentedTo } from '$lib/consent'
2
+ import { isPixelAllowed } from '$lib/pixel'
3
+ import { beforeEach, describe, expect, it, vi } from 'vitest'
4
+
5
+ vi.mock('$lib/consent', () => ({
6
+ hasConsentedTo: vi.fn(() => true),
7
+ }))
8
+
9
+ describe('pixel.ts', () => {
10
+ beforeEach(() => {
11
+ // @ts-ignore
12
+ window.PlayPilotLinkInjections = {}
13
+
14
+ vi.mocked(hasConsentedTo).mockImplementation(() => true)
15
+ })
16
+
17
+ describe('isPixelAllow', () => {
18
+ it('Should return false if no config object is set', () => {
19
+ vi.mocked(hasConsentedTo).mockImplementation(() => true)
20
+ window.PlayPilotLinkInjections.config = null
21
+
22
+ expect(isPixelAllowed()).toBe(false)
23
+ })
24
+
25
+ it('Should return false if config object is without allow_retargeting_pixels', () => {
26
+ vi.mocked(hasConsentedTo).mockImplementation(() => true)
27
+ window.PlayPilotLinkInjections.config = { something: true }
28
+
29
+ expect(isPixelAllowed()).toBe(false)
30
+ })
31
+
32
+ it('Should return false if config object is allow_retargeting_pixels is false', () => {
33
+ vi.mocked(hasConsentedTo).mockImplementation(() => true)
34
+ window.PlayPilotLinkInjections.config = { allow_retargeting_pixels: false }
35
+
36
+ expect(isPixelAllowed()).toBe(false)
37
+ })
38
+
39
+ it('Should return true if config object is allow_retargeting_pixels is true', () => {
40
+ vi.mocked(hasConsentedTo).mockImplementation(() => true)
41
+ window.PlayPilotLinkInjections.config = { allow_retargeting_pixels: true }
42
+
43
+ expect(isPixelAllowed()).toBe(true)
44
+ })
45
+
46
+ it('Should return true if config object is allow_retargeting_pixels is true but hasConsentedTo is false', () => {
47
+ vi.mocked(hasConsentedTo).mockImplementation(() => false)
48
+ window.PlayPilotLinkInjections.config = { allow_retargeting_pixels: true }
49
+
50
+ expect(isPixelAllowed()).toBe(false)
51
+ })
52
+ })
53
+ })
@@ -1,6 +1,6 @@
1
1
  import { describe, it, expect, vi, beforeEach } from 'vitest'
2
2
 
3
- import { fireQueuedTrackingEvents, isPixelAllowed, queueTrackingEvent, setTrackingSids, track } from '$lib/tracking'
3
+ import { fireQueuedTrackingEvents, queueTrackingEvent, setTrackingSids, track } from '$lib/tracking'
4
4
  import { title } from '$lib/fakeData'
5
5
  import { getFullUrlPath } from '$lib/url'
6
6
  import { fakeFetch } from '../helpers'
@@ -299,41 +299,4 @@ describe('$lib/tracking', () => {
299
299
  expect(global.fetch).toHaveBeenCalledTimes(2)
300
300
  })
301
301
  })
302
-
303
- describe('isPixelAllow', () => {
304
- it('Should return false if no config object is set', () => {
305
- vi.mocked(hasConsentedTo).mockImplementation(() => true)
306
- window.PlayPilotLinkInjections.config = null
307
-
308
- expect(isPixelAllowed()).toBe(false)
309
- })
310
-
311
- it('Should return false if config object is without allow_retargeting_pixels', () => {
312
- vi.mocked(hasConsentedTo).mockImplementation(() => true)
313
- window.PlayPilotLinkInjections.config = { something: true }
314
-
315
- expect(isPixelAllowed()).toBe(false)
316
- })
317
-
318
- it('Should return false if config object is allow_retargeting_pixels is false', () => {
319
- vi.mocked(hasConsentedTo).mockImplementation(() => true)
320
- window.PlayPilotLinkInjections.config = { allow_retargeting_pixels: false }
321
-
322
- expect(isPixelAllowed()).toBe(false)
323
- })
324
-
325
- it('Should return true if config object is allow_retargeting_pixels is true', () => {
326
- vi.mocked(hasConsentedTo).mockImplementation(() => true)
327
- window.PlayPilotLinkInjections.config = { allow_retargeting_pixels: true }
328
-
329
- expect(isPixelAllowed()).toBe(true)
330
- })
331
-
332
- it('Should return true if config object is allow_retargeting_pixels is true but hasConsentedTo is false', () => {
333
- vi.mocked(hasConsentedTo).mockImplementation(() => false)
334
- window.PlayPilotLinkInjections.config = { allow_retargeting_pixels: true }
335
-
336
- expect(isPixelAllowed()).toBe(false)
337
- })
338
- })
339
302
  })
@@ -13,6 +13,9 @@ vi.mock('$lib/consent', () => ({
13
13
 
14
14
  vi.mock('$lib/tracking', () => ({
15
15
  track: vi.fn(),
16
+ }))
17
+
18
+ vi.mock('$lib/pixel', () => ({
16
19
  isPixelAllowed: vi.fn(),
17
20
  }))
18
21
 
@@ -6,6 +6,9 @@ import { hasConsentedTo } from '$lib/consent'
6
6
 
7
7
  vi.mock('$lib/tracking', () => ({
8
8
  track: vi.fn(),
9
+ }))
10
+
11
+ vi.mock('$lib/pixel', () => ({
9
12
  isPixelAllowed: vi.fn(),
10
13
  }))
11
14
 
@@ -9,6 +9,9 @@ import { getContext } from 'svelte'
9
9
 
10
10
  vi.mock('$lib/tracking', () => ({
11
11
  track: vi.fn(),
12
+ }))
13
+
14
+ vi.mock('$lib/pixel', () => ({
12
15
  isPixelAllowed: vi.fn(),
13
16
  }))
14
17
 
@@ -9,6 +9,9 @@ import { isYouTubeVideoAvailableInRegion } from '$lib/api/youtubeAvailability'
9
9
 
10
10
  vi.mock('$lib/tracking', () => ({
11
11
  track: vi.fn(),
12
+ }))
13
+
14
+ vi.mock('$lib/pixel', () => ({
12
15
  isPixelAllowed: vi.fn(),
13
16
  }))
14
17
 
@@ -13,6 +13,9 @@ vi.mock('$lib/consent', () => ({
13
13
 
14
14
  vi.mock('$lib/tracking', () => ({
15
15
  track: vi.fn(),
16
+ }))
17
+
18
+ vi.mock('$lib/pixel', () => ({
16
19
  isPixelAllowed: vi.fn(),
17
20
  }))
18
21