PageSourceSearch

https://www.ruhrnachrichten.de/wp-content/plugins/rumble-engine-co…/assets/tracking.js?ver=1.8.0

js ruhrnachrichten.de collected 2026-09-24 08:41:23 UTC 5,076 bytes, 215 lines download raw bytes

1'use strict';
2{
3	let trackingEnabled = false;
4	let trackingInitialized = false;
5	const trackedTeasers = new Set();
6
7	const getTeaserData = ( teaser ) => {
8		try {
9			const teaserData = JSON.parse( teaser.dataset.drive ?? '' );
10			if (
11				typeof teaserData?.article_id !== 'string' ||
12				teaserData.article_id === '' ||
13				typeof teaserData.correlation_id !== 'string' ||
14				teaserData.correlation_id === ''
15			) {
16				return null;
17			}
18
19			return teaserData;
20		} catch {
21			return null;
22		}
23	};
24
25	const sendExposureEvent = ( teaser ) => {
26		if ( ! trackingEnabled || teaser.dataset.exposed !== 'false' ) {
27			return;
28		}
29
30		const teaserData = getTeaserData( teaser );
31		if ( teaserData && typeof window.snowplow === 'function' ) {
32			try {
33				window.snowplow( 'trackSelfDescribingEvent', {
34					schema: 'iglu:de.drive/recommendation_exposure/jsonschema/1-0-0',
35					data: teaserData,
36				} );
37				teaser.dataset.exposed = 'true';
38				intersectionObserver?.unobserve( teaser );
39			} catch {
40				// Keep the teaser eligible for a later tracking attempt.
41			}
42		}
43	};
44
45	const onIntersection = ( entries ) => {
46		for ( const entry of entries ) {
47			if ( entry.isIntersecting ) {
48				sendExposureEvent( entry.target );
49			}
50		}
51	};
52
53	const intersectionObserver =
54		typeof window.IntersectionObserver === 'function'
55			? new window.IntersectionObserver( onIntersection, {
56					threshold: 0.9,
57			  } )
58			: null;
59
60	const sendClickEvent = ( teaser ) => {
61		if ( ! trackingEnabled ) {
62			return;
63		}
64
65		const teaserData = getTeaserData( teaser );
66		if ( teaserData && typeof window.snowplow === 'function' ) {
67			try {
68				window.snowplow( 'trackSelfDescribingEvent', {
69					schema: 'iglu:de.drive/recommendation_click/jsonschema/1-0-0',
70					data: {
71						article_id: teaserData.article_id,
72						correlation_id: teaserData.correlation_id,
73					},
74				} );
75			} catch {
76				// Do not interfere with the visitor following the link.
77			}
78		}
79	};
80
81	const normaliseUrl = ( url ) => {
82		if ( typeof url !== 'string' || url === '' ) {
83			return null;
84		}
85
86		try {
87			const parsedUrl = new URL( url, window.location.href );
88			return `${ parsedUrl.origin }${ parsedUrl.pathname }${ parsedUrl.search }`;
89		} catch {
90			return null;
91		}
92	};
93
94	const createTeaserData = ( items, correlationId, teaser ) => {
95		const teaserLink = teaser.querySelector( '.teaser__title-link' );
96		if ( ! teaserLink ) {
97			return null;
98		}
99
100		const teaserUrl = normaliseUrl( teaserLink.href );
101		const matchingItem = items.find(
102			( item ) =>
103				item &&
104				typeof item === 'object' &&
105				normaliseUrl( item.url ) === teaserUrl &&
106				typeof item.articleId === 'string' &&
107				item.articleId !== ''
108		);
109
110		if ( ! matchingItem ) {
111			return null;
112		}
113
114		return {
115			correlation_id: correlationId,
116			article_id: matchingItem.articleId,
117			is_plus:
118				matchingItem.isPremium === true ||
119				matchingItem.isPremium === 'true',
120			plus_sign_visible: false,
121		};
122	};
123
124	const initTracking = () => {
125		if ( trackingInitialized ) {
126			return;
127		}
128
129		trackingInitialized = true;
130		window.addEventListener( 'teasers-appended', ( event ) => {
131			const container = event.target;
132			const items = event.detail?.items;
133			const correlationId = event.detail?.correlationId;
134
135			if (
136				! container?.classList?.contains( 'drive-experiment-block' ) ||
137				! Array.isArray( items ) ||
138				items.length === 0 ||
139				typeof correlationId !== 'string' ||
140				correlationId === ''
141			) {
142				return;
143			}
144
145			container.querySelectorAll( '.teaser' ).forEach( ( teaser ) => {
146				if ( teaser.dataset.driveTrackingInitialized === 'true' ) {
147					return;
148				}
149
150				const teaserData = createTeaserData(
151					items,
152					correlationId,
153					teaser
154				);
155				if ( ! teaserData ) {
156					return;
157				}
158
159				teaser.dataset.driveTrackingInitialized = 'true';
160				teaser.dataset.drive = JSON.stringify( teaserData );
161				teaser.dataset.exposed = 'false';
162				trackedTeasers.add( teaser );
163				if ( trackingEnabled ) {
164					intersectionObserver?.observe( teaser );
165				}
166
167				teaser.querySelectorAll( 'a' ).forEach( ( link ) =>
168					link.addEventListener( 'click', () => {
169						sendClickEvent( teaser );
170					} )
171				);
172			} );
173		} );
174	};
175
176	const checkIntegrationAllowed = () => {
177		if ( typeof window.__cmp !== 'function' ) {
178			return;
179		}
180
181		const cmpData = window.__cmp( 'getCMPData' );
182		const gtmConsent = cmpData?.vendorConsents?.s905 === true;
183		trackingEnabled = gtmConsent;
184
185		if ( gtmConsent ) {
186			trackedTeasers.forEach( ( teaser ) => {
187				if ( teaser.dataset.exposed === 'false' ) {
188					intersectionObserver?.observe( teaser );
189				}
190			} );
191		} else {
192			intersectionObserver?.disconnect();
193		}
194	};
195
196	const registerConsentListener = () => {
197		if ( typeof window.__cmp !== 'function' ) {
198			return;
199		}
200
201		window.__cmp(
202			'addEventListener',
203			[ 'consent', checkIntegrationAllowed, false ],
204			null
205		);
206		checkIntegrationAllowed();
207	};
208
209  initTracking();
210	if ( typeof window.__cmp === 'undefined' ) {
211		window.addEventListener( 'cmpEvent_init', registerConsentListener );
212	} else {
213		registerConsentListener();
214	}
215}

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.