PageSourceSearch

https://www.packhacker.com/app/themes/packhacker/asc/display-ad.js?ver=8.5.16

js packhacker.com collected 2026-09-24 19:04:02 UTC 20,489 bytes, 689 lines download raw bytes

1// Ad rendering is now handled by asc_prebid.js
2// This file now only handles Google Ads events and targeting
3
4const removeDesktopAdhesion = () => {
5	const desktopAdhesion = document.querySelector( '[class*="packh-desktop-adhesion"]' );
6	const footerElement   = document.querySelector( 'footer.master-footer' );
7
8	desktopAdhesion.remove();
9	footerElement.setAttribute( 'style', '' );
10
11	if ( document.querySelectorAll( '#jw-desktop-override' ).length > 0 ) {
12		document.querySelector( '#jw-desktop-override' ).remove();
13	}
14}
15
16const removeMobileAdhesion = () => {
17	const mobileAdhesion = document.querySelector( '[class*="packh-mobile-adhesion"]' );
18	const footerElement  = document.querySelector( 'footer.master-footer' );
19
20	mobileAdhesion.remove();
21	footerElement.setAttribute( 'style', '' );
22}
23
24const slotRefreshTimers = new Map();
25/** Latest GPT slot object per div id (desktop-sidebar-mpu-*), for pubads.refresh(). */
26const sidebarMpuGptSlots = new Map();
27
28/** True after desktop ph_dt_adhesion* slotRenderEnded with a non-empty creative; false on empty or never shown. */
29let desktopAdhesionCreativeLive = false;
30/** Consecutive polls where DOM says adhesion UI is gone/hidden (debounce refresh flicker). */
31let adhesionDomClosedStreak = 0;
32/** Inner pubads.refresh (native or Ascedeum); updated whenever we re-wrap after asc overwrites us. */
33let packhMergeInnerRefresh = null;
34
35const getRefreshTimeoutMs = ( slotElement ) => {
36	if ( ! slotElement ) {
37		return null;
38	}
39
40	const fromEl = slotElement.closest( '[data-refresh-timeout]' ) || slotElement;
41	const refreshTimeout = Number.parseInt( fromEl.dataset.refreshTimeout || '', 10 );
42
43	if ( Number.isNaN( refreshTimeout ) || refreshTimeout <= 0 ) {
44		return null;
45	}
46
47	return refreshTimeout * 1000;
48};
49
50const isSlotInViewport = ( slotElement ) => {
51	if ( ! slotElement ) {
52		return false;
53	}
54
55	const viewportElement = slotElement.closest( '.packh-desktop-sidebar-mpu' ) || slotElement;
56	const rect = viewportElement.getBoundingClientRect();
57	const viewHeight = window.innerHeight || document.documentElement.clientHeight;
58	const viewWidth = window.innerWidth || document.documentElement.clientWidth;
59
60	if ( rect.width <= 0 || rect.height <= 0 ) {
61		return false;
62	}
63
64	const verticalVisible = Math.min( rect.bottom, viewHeight ) - Math.max( rect.top, 0 );
65	const horizontalVisible = Math.min( rect.right, viewWidth ) - Math.max( rect.left, 0 );
66
67	if ( verticalVisible <= 0 || horizontalVisible <= 0 ) {
68		return false;
69	}
70
71	const visibleArea = verticalVisible * horizontalVisible;
72	const elementArea = rect.width * rect.height;
73
74	// Tall MPUs often have <50% of their area in view; 10% is enough to count as "in view".
75	return elementArea > 0 && ( visibleArea / elementArea ) >= 0.1;
76};
77
78const isStickySidebarMpuRefreshSlot = ( slotElementId, domEl ) => {
79	if ( ! slotElementId || ! slotElementId.startsWith( 'desktop-sidebar-mpu' ) ) {
80		return false;
81	}
82
83	if ( ! domEl || ! getRefreshTimeoutMs( domEl ) ) {
84		return false;
85	}
86
87	return true;
88};
89
90const findSidebarSlotElement = ( slotElementId ) => {
91	if ( ! slotElementId ) {
92		return null;
93	}
94
95	let el = document.getElementById( slotElementId );
96
97	if ( el ) {
98		return el;
99	}
100
101	try {
102		if ( typeof CSS !== 'undefined' && CSS.escape ) {
103			return document.querySelector( '#' + CSS.escape( slotElementId ) );
104		}
105	} catch ( err ) {
106		return null;
107	}
108
109	return null;
110};
111
112const isDesktopAdhesionSlot = ( slot ) => {
113	if ( ! slot || typeof slot.getAdUnitPath !== 'function' ) {
114		return false;
115	}
116
117	try {
118		const path = slot.getAdUnitPath() || '';
119
120		if ( path.indexOf( 'ph_mob_adhesion' ) !== -1 ) {
121			return false;
122		}
123
124		return path.indexOf( 'ph_dt_adhesion' ) !== -1;
125	} catch ( err ) {
126		return false;
127	}
128};
129
130const isDesktopAdhesionSlotEvent = ( event ) => {
131	if ( ! event || ! event.slot ) {
132		return false;
133	}
134
135	return isDesktopAdhesionSlot( event.slot );
136};
137
138const getStickySidebarSlotsForMerge = () => Array.from( sidebarMpuGptSlots.values() ).filter( Boolean );
139
140const syncSidebarFallbackTimersForAdhesionState = () => {
141	if ( desktopAdhesionCreativeLive ) {
142		for ( const id of sidebarMpuGptSlots.keys() ) {
143			clearSidebarMpuRefreshTimer( id );
144		}
145
146		return;
147	}
148
149	for ( const id of sidebarMpuGptSlots.keys() ) {
150		const el = findSidebarSlotElement( id );
151
152		if ( el && getRefreshTimeoutMs( el ) ) {
153			ensureSidebarMpuRefreshTimer( id );
154		}
155	}
156};
157
158const onDesktopAdhesionSlotRenderEnded = ( event ) => {
159	if ( ! isDesktopAdhesionSlotEvent( event ) ) {
160		return;
161	}
162
163	desktopAdhesionCreativeLive = ! event.isEmpty;
164	adhesionDomClosedStreak = 0;
165	syncSidebarFallbackTimersForAdhesionState();
166};
167
168const isHiddenByDisplayOrVisibility = ( el ) => {
169	let node = el;
170
171	while ( node && node !== document.documentElement ) {
172		if ( node.nodeType === 1 ) {
173			const st = window.getComputedStyle( node );
174
175			if ( st.display === 'none' || st.visibility === 'hidden' ) {
176				return true;
177			}
178		}
179
180		node = node.parentNode;
181	}
182
183	return false;
184};
185
186/** Desktop adhesion ot-name nodes still visible (user close often removes or hides). */
187const isDesktopAdhesionOpenInDom = () => {
188	const attrs = [ 'ph_dt_adhesion', 'ph_dt_adhesion_bg' ];
189
190	for ( let i = 0; i < attrs.length; i++ ) {
191		const node = document.querySelector( '[ot-name="' + attrs[ i ] + '"]' );
192
193		if ( ! node || ! document.body.contains( node ) ) {
194			continue;
195		}
196
197		if ( isHiddenByDisplayOrVisibility( node ) ) {
198			continue;
199		}
200
201		const r = node.getBoundingClientRect();
202
203		if ( r.width >= 2 && r.height >= 2 ) {
204			return true;
205		}
206	}
207
208	return false;
209};
210
211const pollAdhesionDomUiState = () => {
212	if ( ! desktopAdhesionCreativeLive ) {
213		adhesionDomClosedStreak = 0;
214		return;
215	}
216
217	const desktopMq = window.matchMedia( '(min-width: 992px)' );
218
219	if ( ! desktopMq.matches ) {
220		adhesionDomClosedStreak = 0;
221		return;
222	}
223
224	if ( isDesktopAdhesionOpenInDom() ) {
225		adhesionDomClosedStreak = 0;
226		return;
227	}
228
229	adhesionDomClosedStreak++;
230
231	if ( adhesionDomClosedStreak >= 3 ) {
232		adhesionDomClosedStreak = 0;
233		desktopAdhesionCreativeLive = false;
234		syncSidebarFallbackTimersForAdhesionState();
235	}
236};
237
238/**
239 * When asc_prebid loads after display-ad (async vs defer), it can replace pubads.refresh and drop our
240 * merge. Re-chain whenever refresh is no longer our outer wrapper.
241 */
242const packhMergeOuterRefresh = function () {
243	const pubads = googletag.pubads();
244	const inner = packhMergeInnerRefresh;
245
246	if ( typeof inner !== 'function' ) {
247		return;
248	}
249
250	const stickySlots = getStickySidebarSlotsForMerge();
251	const desktopMq = window.matchMedia( '(min-width: 992px)' );
252
253	if ( ! stickySlots.length || ! desktopMq.matches ) {
254		return inner.apply( pubads, arguments );
255	}
256
257	const slots = arguments[ 0 ];
258	const tail = Array.prototype.slice.call( arguments, 1 );
259
260	if ( arguments.length === 0 || slots === undefined || slots === null ) {
261		return inner.apply( pubads, arguments );
262	}
263
264	let slotList = Array.isArray( slots ) ? slots.slice() : [ slots ];
265
266	if ( ! slotList.length ) {
267		return inner.apply( pubads, arguments );
268	}
269
270	let hasDesktopAdhesion = false;
271
272	for ( let i = 0; i < slotList.length; i++ ) {
273		if ( isDesktopAdhesionSlot( slotList[ i ] ) ) {
274			hasDesktopAdhesion = true;
275			break;
276		}
277	}
278
279	if ( ! hasDesktopAdhesion ) {
280		return inner.apply( pubads, arguments );
281	}
282
283	for ( let s = 0; s < stickySlots.length; s++ ) {
284		const sticky = stickySlots[ s ];
285
286		if ( slotList.indexOf( sticky ) === -1 ) {
287			slotList.push( sticky );
288		}
289	}
290
291	return inner.apply( pubads, [ slotList ].concat( tail ) );
292};
293
294const ensurePackhSidebarRefreshMergePatch = () => {
295	if ( ! googletag || typeof googletag.pubads !== 'function' ) {
296		return;
297	}
298
299	const pubads = googletag.pubads();
300
301	if ( ! pubads || typeof pubads.refresh !== 'function' ) {
302		return;
303	}
304
305	if ( pubads.refresh === packhMergeOuterRefresh ) {
306		return;
307	}
308
309	packhMergeInnerRefresh = pubads.refresh.bind( pubads );
310	pubads.refresh = packhMergeOuterRefresh;
311};
312
313const clearSidebarMpuRefreshTimer = ( slotElementId ) => {
314	if ( slotRefreshTimers.has( slotElementId ) ) {
315		clearInterval( slotRefreshTimers.get( slotElementId ) );
316		slotRefreshTimers.delete( slotElementId );
317	}
318};
319
320const ensureSidebarMpuRefreshTimer = ( slotElementId ) => {
321	if ( desktopAdhesionCreativeLive ) {
322		return;
323	}
324
325	if ( slotRefreshTimers.has( slotElementId ) ) {
326		return;
327	}
328
329	const domEl = findSidebarSlotElement( slotElementId );
330	const timeoutMs = getRefreshTimeoutMs( domEl );
331
332	if ( ! timeoutMs ) {
333		return;
334	}
335
336	const timerId = setInterval( () => {
337		if ( desktopAdhesionCreativeLive ) {
338			return;
339		}
340
341		if ( document.hidden ) {
342			return;
343		}
344
345		const gptSlot = sidebarMpuGptSlots.get( slotElementId );
346
347		if ( ! gptSlot ) {
348			return;
349		}
350
351		const currentSlotElement = findSidebarSlotElement( slotElementId );
352
353		if ( ! currentSlotElement || ! document.body.contains( currentSlotElement ) ) {
354			return;
355		}
356
357		if ( ! isSlotInViewport( currentSlotElement ) ) {
358			return;
359		}
360
361		googletag.cmd.push( () => {
362			googletag.pubads().refresh( [ gptSlot ] );
363		} );
364	}, timeoutMs );
365
366	slotRefreshTimers.set( slotElementId, timerId );
367};
368
369/**
370 * Capture the live GPT slot on slotRenderEnded and refresh using that reference (Google pattern).
371 */
372const registerStickySidebarMpuRefresh = ( event, retryCount = 0 ) => {
373	const slotElementId = event.slot.getSlotElementId();
374
375	if ( ! slotElementId || ! slotElementId.startsWith( 'desktop-sidebar-mpu' ) ) {
376		return;
377	}
378
379	if ( event.isEmpty ) {
380		clearSidebarMpuRefreshTimer( slotElementId );
381		sidebarMpuGptSlots.delete( slotElementId );
382		return;
383	}
384
385	const domEl = findSidebarSlotElement( slotElementId );
386
387	if ( ! domEl ) {
388		if ( retryCount < 3 ) {
389			setTimeout( () => registerStickySidebarMpuRefresh( event, retryCount + 1 ), 1000 );
390		}
391
392		return;
393	}
394
395	if ( ! isStickySidebarMpuRefreshSlot( slotElementId, domEl ) ) {
396		return;
397	}
398
399	// Always keep the latest slot object from GPT for this div id.
400	sidebarMpuGptSlots.set( slotElementId, event.slot );
401
402	if ( getRefreshTimeoutMs( domEl ) && ! desktopAdhesionCreativeLive ) {
403		ensureSidebarMpuRefreshTimer( slotElementId );
404	}
405};
406
407let mobileScrollerId = 'mobile-interscroller';
408
409var googletag = googletag || {};
410googletag.cmd = googletag.cmd || [];
411
412googletag.cmd.push( () => {
413	ensurePackhSidebarRefreshMergePatch();
414
415	googletag.pubads().addEventListener( 'slotOnload', function( event ) {
416		if ( event.slot.getSlotElementId().includes( 'desktop-adhesion' ) ) {
417			const footerElement = document.querySelector( 'footer.master-footer' );
418			const desktopAdhesion = document.querySelectorAll( '[class*="packh-desktop-adhesion"]' );
419			
420			let slotElement = document.querySelector( '#' + event.slot.getSlotElementId() );
421			let divElement = slotElement.querySelector('div[id*="google_ads_iframe"]');
422			let divDisplayStyle = divElement.style.display;
423
424			if ( event.isEmpty || 'none' == divDisplayStyle ) {
425				// hide unit
426				desktopAdhesion[0].style.display = 'none';
427				footerElement.setAttribute( 'style', '' );
428			} else {
429
430				if ( desktopAdhesion.length > 0 ) {
431					desktopAdhesion[0].style.display = 'block';
432					
433					// add close button
434					if ( document.querySelectorAll( '[class*="packh-desktop-adhesion"] #close' ).length < 1 ) {
435						let closeButton = document.createElement( 'button' );
436						closeButton.type = 'button';
437						closeButton.id = 'close';
438						closeButton.setAttribute( 'onclick', 'removeDesktopAdhesion()' );
439						closeButton.innerHTML = '&times;'
440						desktopAdhesion[0].appendChild( closeButton );
441					}
442
443					footerElement.style.paddingBottom = ( divElement.clientHeight + 50 ) + 'px';
444
445					if ( document.querySelectorAll( '#jw-desktop-override' ).length > 0 ) {
446						document.querySelector( '#jw-desktop-override' ).remove();
447					}
448					
449					const style = document.createElement('style');
450					style.id = 'jw-desktop-override';
451
452					style.textContent = `
453					@media screen and ( min-width: 992px ) {
454						.jw-flag-floating.jw-floating-dismissible .jw-wrapper {
455							bottom: ` + ( divElement.clientHeight + 50 ) + `px !important;
456						}
457					}
458					`;
459
460					document.head.appendChild(style);
461				}
462			}
463		}
464
465		if ( event.slot.getSlotElementId().includes( 'mobile-adhesion' ) ) {
466			const footerElement = document.querySelector( 'footer.master-footer' );
467			const mobileAdhesion = document.querySelectorAll( '[class*="packh-mobile-adhesion"]' );
468			let slotElement      = document.querySelector( '#' + event.slot.getSlotElementId() );
469			let divElement       = slotElement.querySelector('div[id*="google_ads_iframe"]');
470
471			if ( event.isEmpty || 'none' == divDisplayStyle ) {
472				// hide unit
473				mobileAdhesion[0].style.display = 'none';
474				footerElement.setAttribute( 'style', '' );
475			} else {
476				if ( mobileAdhesion.length > 0 ) {
477					mobileAdhesion[0].style.display = 'block';
478					
479					// add close button
480					if ( document.querySelectorAll( '[class*="packh-mobile-adhesion"] #close' ).length < 1 ) {
481						var closeButton = document.createElement( 'button' );
482						closeButton.type = 'button';
483						closeButton.id = 'close';
484						closeButton.setAttribute( 'onclick', 'removeMobileAdhesion()' );
485						closeButton.innerHTML = '&times;'
486						mobileAdhesion[0].appendChild( closeButton );
487					}
488
489					footerElement.style.paddingBottom = ( divElement.clientHeight + 50 ) + 'px';
490				}
491			}
492		}
493
494		if ( event.slot.getSlotElementId().includes( mobileScrollerId ) ) {
495			
496			var slotElement     = document.querySelector( '#' + event.slot.getSlotElementId() );
497			var divElement      = slotElement.querySelector( 'div[id*="google_ads_iframe"]' );
498			var divDisplayStyle = divElement.style.display;
499			
500			if ( 'none' == divDisplayStyle ) {
501				document.querySelector( '#interscroller-wrapper' ).parentNode.style.display = 'none';
502				return;
503			}
504		}
505	} );
506
507	googletag.pubads().addEventListener( 'slotRenderEnded', function ( event ) {
508		// removed code settingt the long refresh timeout as ascendeum will turn off refreshing on their end.
509		onDesktopAdhesionSlotRenderEnded( event );
510		registerStickySidebarMpuRefresh( event );
511
512		if ( event.slot.getSlotElementId().includes( mobileScrollerId ) ) {
513			var slotElement     = document.querySelector( '#' + event.slot.getSlotElementId() );
514			var divElement      = slotElement.querySelector( 'div[id*="google_ads_iframe"]' );
515			var divDisplayStyle = divElement.style.display;
516			
517			if ( 'none' == divDisplayStyle ) {
518				document.querySelector( '#interscroller-wrapper' ).parentNode.style.display = 'none';
519				return;
520			}
521
522			if ( ! event.isEmpty ) {
523				var topLabelCheck = document.querySelectorAll( '#adlabel-top' );
524				var bottomLabelCheck = document.querySelectorAll( '#adlabel-bottom' );
525
526				var labelText = 'Advertisement';
527				var lt        = document.createTextNode( labelText );
528				var ltbt      = document.createTextNode( labelText );
529
530				if ( topLabelCheck.length < 1 ) {
531					var adlabel   = document.createElement("div");
532					adlabel.id    = 'adlabel-top';
533					adlabel.appendChild( lt );
534					adlabel.setAttribute( 'style', 'position:absolute; z-index:9; margin-top:-26px; color:#fff; background-color:#222; text-align:center; width:100%; left:0;font-size:14px; padding:3px 0; height:26px' );
535					document.getElementById( 'inscroll-banner' ).appendChild( adlabel );
536				}
537
538				if ( bottomLabelCheck.length < 1 ) {
539					var adlabelbt = document.createElement("div");
540					adlabelbt.id  = 'adlabel-bottom';
541					adlabelbt.appendChild( ltbt );
542					adlabelbt.setAttribute( 'style', 'position:absolute; z-index:9; bottom:-26px;
542 color:#fff; background-color:#222; text-align:center; width:100%; left:0;font-size:14px; padding:3px 0; height:26px' );
543					document.getElementById( 'inscroll-banner' ).appendChild( adlabelbt );
544				}
545
546				document.getElementById( 'interscroller-wrapper' )
547					.setAttribute( 'style', 'margin-left:-15px; margin-right:-15px; overflow: hidden;' );
548
549				document.getElementById( 'inscroll-banner' )
550					.setAttribute( 'style', 'height: 100vh; position: relative; margin: 40px 0;' );
551
552				document.getElementById( 'banner-core' )
553					.setAttribute( 'style', 'width: 100%; top: 0; left: 0; clip: rect(0,100vw,100vh,0); overflow-x: hidden; overflow-y: auto; position: fixed; -webkit-transform: translateZ(0); -moz-transform: translateZ(0); transform: translateZ(0);' );
554				
555				document.getElementById( 'iscroll-clip' )
556					.setAttribute( 'style', 'display: flex !important; align-items: center; justify-content: center; width: 100vw; height: 100vh;' );
557
558				document.querySelector( 'div[id*=' + mobileScrollerId + ']' )
559					.setAttribute( 'style', 'width:100vw !important; height:100vh !important; overflow: hidden !important;' );
560
561				document.querySelector( 'div[id*=' + mobileScrollerId + '] div[id*="google_ads_iframe"]' )
562					.setAttribute( 'style', 'width:100vw !important; height:100vh !important;' );
563
564				document.querySelector( 'div[id*=' + mobileScrollerId + '] iframe[id*="google_ads_iframe"]' )
565					.setAttribute( 'style', 'width:100vw !important; height:100vh !important; overflow: hidden !important;' );
566
567				document.querySelector( 'div[id*=' + mobileScrollerId + '] iframe' )
568					.setAttribute( 'scrolling', 'no' );
569
570				let hasAdventive = document.querySelectorAll( 'div[id*=' + mobileScrollerId + '] div[id*="adventive"]' ).length;
571				
572				if ( hasAdventive > 0 ) {
573					document.querySelector( 'div[id*=' + mobileScrollerId + '] iframe' )
574						.setAttribute( 'style', 'display: none;' );
575				}
576
577				window.onscroll = function () {
578					let inner        = document.getElementById( 'banner-core' );
579					let pos          = document.getElementById( 'inscroll-banner' ).getBoundingClientRect();
580					let test         = document.querySelectorAll( 'div[id*=' + mobileScrollerId + ']' ).length;
581					inner.style.clip = "rect(" + pos.top + "px,100vw," + pos.bottom + "px,0)";
582				}
583
584				window.onscroll();
585			}
586		}
587	} );
588
589	setInterval( pollAdhesionDomUiState, 1000 );
590	setInterval( ensurePackhSidebarRefreshMergePatch, 1500 );
591	googletag.cmd.push( () => {
592		ensurePackhSidebarRefreshMergePatch();
593	} );
594
595	// removed refresh adhesion logic to avoid double refresh
596
597	const keys = Object.keys( window.PH_View );
598	keys.forEach( function( key ) {
599		googletag.pubads().setTargeting( key, window.PH_View[ key ] );
600	} );
601
602	// Add UTM targeting
603	const urlParams = new URLSearchParams(window.location.search);
604	const campaign = urlParams.get('utm_campaign');
605	let targetingValue = '';
606	let targetingValue2 = '';
607
608	if ( urlParams.has( 'utm_medium' ) ) {
609		googletag.pubads().setTargeting( 'utm_medium', urlParams.get( 'utm_medium' ) );
610	}
611
612	if ( urlParams.has( 'utm_campaign' ) ) {
613		googletag.pubads().setTargeting( 'utm_campaign', urlParams.get( 'utm_campaign' ) );
614	}
615
616	if ( urlParams.has( 'utm_source' ) ) {
617		googletag.pubads().setTargeting( 'utm_source', urlParams.get( 'utm_source' ) );
618	}
619	
620	if ( urlParams.has( 'utm_content' ) ) {
621		googletag.pubads().setTargeting( 'utm_content', urlParams.get( 'utm_content' ) );
622	}
623	
624	if( campaign ){
625		targetingValue2 = campaign;
626		switch(true){
627			// hr_nr
628			case campaign.includes('h_nr_0'):
629				targetingValue = 'bwboost_nr_0';
630				break;
631			case campaign.includes('h_nr_i'):
632				targetingValue = 'bwboost_nr_i';
633				break;
634			case campaign.includes('h_nr_f'):
635				targetingValue = 'bwboost_nr_f';
636				break;
637
638			// h_gj
639			case campaign.includes('h_gj_0'):
640				targetingValue = 'bwboost_gj_0';
641				break;
642				case campaign.includes('h_gj_i'):
643				targetingValue = 'bwboost_gj_i';
644				break;
645			case campaign.includes('h_gj_f'):
646				targetingValue = 'bwboost_gj_f';
647				break;
648			
649			// h_ph
650			case campaign.includes('h_ph_0'):
651				targetingValue = 'bwboost_ph_0';
652				break;
653				case campaign.includes('h_ph_i'):
654				targetingValue = 'bwboost_ph_i';
655				break;
656			case campaign.includes('h_ph_f'):
657				targetingValue = 'bwboost_ph_f';
658				break;
659
660			// h_sb
661			case campaign.includes('h_sb_0'):
662				targetingValue = 'bwboost_sb_0';
663				break;
664			case campaign.includes('h_sb_i'):
665				targetingValue = 'bwboost_sb_i';
666				break;
667			case campaign.includes('h_sb_f'):
668				targetingValue = 'bwboost_sb_f';
669				break;
670
671			// h_ir
672			case campaign.includes('h_ir_0'):
673				targetingValue = 'bwboost_ir_0';
674				break;
675			case campaign.includes('h_ir_1'):
676				targetingValue = 'bwboost_ir_1';
677				break;
678			case campaign.includes('h_ir_f'):
679				targetingValue = 'bwboost_ir_f';
680				break;
681		}
682		
683		if(targetingValue !== ''){
684			googletag.pubads().setTargeting('utm', targetingValue);
685		}
686
687		googletag.pubads().setTargeting('utm_bwcampaign', targetingValue2);
688	}
689} );

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.