PageSourceSearch

https://www.customerexperiencedive.com/static/js/prestitial.js?520919230926

js customerexperiencedive.com collected 2026-09-24 17:18:44 UTC 8,397 bytes, 248 lines download raw bytes

1(function() {
2  var prestitialAds = {
3
4    daysBetweenPrestitial: 7,
5    defaultTimeoutSeconds: 15,
6
7    testing: function() {
8      return document.location.search.indexOf('prestitial_test') !== -1;
9    },
10
11    testingNoAd: function() {
12      return this.testing() === true && document.location.search.indexOf('no_ad') !== -1;
13    },
14
15    overrideTimeout: function() {
16      return this.testing() === true && document.location.search.match('no_timeout') !== null;
17    },
18
19    timeoutSeconds: function() {
20      return this.defaultTimeoutSeconds * 1000;
21    },
22
23    setPrestitialPossibleCookie: function() {
24      // "possible" prestitial tracking for ad inventory reporting. _prestitialViewed is used
25      //  for deciding whether or not it's time to show the ad
26      if (document.cookie.indexOf('_prestitialPossible') === -1) {
27        this.setCookie(
28          '_prestitialPossible',
29          Date.now(),
30          this.daysBetweenPrestitial
31        );
32      }
33    },
34
35    setCookie: function(cName, value, expireDays) {
36      var exdate = new Date();
37      exdate.setDate(exdate.getDate() + expireDays);
38      document.cookie =
39        cName + '=' + encodeURIComponent(value)
40        + ((expireDays === null) ? '' : ';expires=' + exdate.toUTCString())
41        + '; path=/';
42    },
43
44    screenMeetsSizeReqs: function() {
45      // Figure out if window is wide/high enough to show a prestitial
46      return (window.innerWidth > 640 && window.innerHeight > 640);
47    },
48
49    userIsPrestitialEligible: function() {
50      return (
51        (document.cookie.indexOf('_prestitialViewed') === -1)
52        && (window.location.href.indexOf('?prestitial_skip') === -1)
53      );
54    },
55
56    userIsNotOnSearchPage: function() {
57      // Don't show prestitial on search page
58      return !window.location.href.includes('/search/');
59    },
60
61    pageIsPrestitialEligible: function() {
62      // override if we are forcing a test
63      if (this.testing() === true) {
64        return true;
65      }
66      // Check 3 conditions:
67      // 1. The screen size meets minimum requirements
68      // 2. User is eligible (via cookies).
69      // 3. User is not on search page
70      return (
71        this.screenMeetsSizeReqs() === true &&
72        this.userIsPrestitialEligible() === true &&
73        this.userIsNotOnSearchPage()
74      );
75    },
76
77    logClosePrestitialAdBy: function(closedBy) {  // eslint-disable-line no-unused-vars
78      // No longer logged per TECH-8759
79    },
80
81    showOverlay: function() {
82      document.body.style.overflow = 'hidden';
83      document.querySelector('div#prestitial-init').style.display = 'block';
84    },
85
86    initialize: function(daysBetweenPrestitial) {
87      if (typeof daysBetweenPrestitial === 'undefined') {
88        // Not sure if we still need the variable being set at the top of this file via daysBetweenPrestitial = 7
89        this.daysBetweenPrestitial = 7;
90      } else {
91        this.daysBetweenPrestitial = daysBetweenPrestitial;
92      }
93
94      // Alias because "this" is a different namespace in the next chunk.
95      var closeFunc = this.logClosePrestitialAdBy;
96      var hideFunc = this.closePrestitial.bind(this);
97
98      // Cache references to prestitial elements
99      this.prestitialInit = document.querySelector('#prestitial-init');
100      this.prestitialOuter = document.querySelector('#prestitial-outer');
101      this.prestitialOOP = document.querySelector('#prestitial-oop');
102
103      // Get reference to prestitial but DON'T show yet
104      // Wait for OOP check in slotRenderEnded event
105      this.prestitialOuter.addEventListener('click', function() {
106        closeFunc('user');
107        hideFunc();
108      });
109    },
110
111    showStandardPrestitial: function() {
112      if (this.prestitialOuter) {
113        this.prestitialOuter.style.display = 'block';
114      }
115    },
116
117    showOOPPrestitial: function() {
118      if (this.prestitialOOP) {
119        this.prestitialOOP.style.display = 'block';
120      }
121    },
122
123    closePrestitial: function() {
124      // close all prestitial things and set the body overflow back to default
125      document.body.style.overflow = '';
126      if (this.prestitialInit) this.prestitialInit.style.display = 'none';
127      if (this.prestitialOuter) this.prestitialOuter.style.display = 'none';
128      if (this.prestitialOOP) this.prestitialOOP.style.display = 'none';
129    },
130
131    prestitialAdIsClosed: function() {
132      // Replacement for jQuery :visible psuedo selector
133      var isVisible = function(elem) {
134        return elem && !!(elem.offsetWidth || elem.offsetHeight || elem.getClientRects().length);
135      };
136      return (
137        !isVisible(this.prestitialOuter)
138        && !isVisible(this.prestitialInit)
139        && !isVisible(this.prestitialOOP)
140      );
141    },
142
143    sentPrestitialEligibleEvent: function() {
144      // wait for obd adn the diagnosticPrintOut object to be available
145      if (typeof window.obd?.diagnosticPrintOut === 'undefined') {
146        setTimeout(this.sentPrestitialEligibleEvent.bind(this), 100);
147        return;
148      }
149      // check if all keys in the diagnosticPrintOut object are true
150      var allKeysTrue = Object.keys(window.obd.diagnosticPrintOut).every(function(key) {
151        return window.obd.diagnosticPrintOut[key] === true;
152      });
153      // if all keys are true, send the event
154      if (allKeysTrue) {
155        var eventObject = {
156          'event': 'user.prestitial',
157          'user.prestitial': {
158            'name': 'Prestitial Eligible',
159            'eligible': 1,
160          },
161        };
162        window.pushGTMEvent(eventObject);
163      }
164    },
165
166    MIN_VISIBLE_OOP_CONTENT_SIZE: 10,
167
168    hasVisibleOOPContent: function() {
169      // Consider the OOP slot to have real content once an iframe inside it
170      // exceeds this size, rather than checking for a specific vendor's
171      // element (e.g. Airtory's #air_init_holder). Vendor element IDs/classes
172      // are implementation details that can change without notice, and this
173      // doesn't depend on any of them.
174      //
175      // Scoped to iframes specifically (not just any element): ad creatives
176      // are always delivered inside an iframe, while GAM's own wrapper divs
177      // can have non-trivial incidental size (e.g. a container div that's
178      // ~20px tall before the creative renders) that has nothing to do with
179      // whether an ad is actually visible. Checking only iframes avoids
180      // mistaking that scaffolding for real content.
181      //
182      // The size threshold exists because GPT's own 1x1 tracking iframe stays
183      // in the DOM the entire time regardless of the creative's state, so a
184      // plain "is anything non-zero-size" check would never tell a real ad
185      // apart from GPT's own bookkeeping iframe.
186      if (!this.prestitialOOP) return false;
187
188      const iframes = this.prestitialOOP.querySelectorAll('iframe');
189      for (let i = 0; i < iframes.length; i++) {
190        const el = iframes[i];
191        if (
192          el.offsetWidth > this.MIN_VISIBLE_OOP_CONTENT_SIZE &&
193          el.offsetHeight > this.MIN_VISIBLE_OOP_CONTENT_SIZE
194        ) {
195          return true;
196        }
197      }
198      return false;
199    },
200
201    waitForOOPAdContent: function(callback) {
202      const maxAttempts = 50;
203      let attempts = 0;
204      const self = this;
205
206      const checkInterval = setInterval(function() {
207        attempts += 1;
208
209        if (self.hasVisibleOOPContent()) {
210          clearInterval(checkInterval);
211          callback();
212        } else if (attempts >= maxAttempts) {
213          // Give up after ~2.5 seconds (50 * 50ms)
214          clearInterval(checkInterval);
215          callback(); // Hide overlay anyway
216        }
217      }, 50); // Check every 50ms
218    },
219
220    watchForOOPAdClose: function(callback) {
221      if (!this.prestitialOOP) return;
222      const self = this;
223
224      if (!self.hasVisibleOOPContent()) {
225        // Nothing ever rendered, so there's no visible-to-hidden transition
226        // left to wait for. Close now instead of leaving the wrapper open
227        // indefinitely.
228        callback();
229        return;
230      }
231
232      const observer = new MutationObserver(function() {
233        if (!self.hasVisibleOOPContent()) {
234          observer.disconnect();
235          callback();
236        }
237      });
238
239      observer.observe(this.prestitialOOP, {
240        attributes: true,
241        childList: true,
242        subtree: true,
243      });
244    },
245  };
246
247  window.prestitialAds = prestitialAds;
248})();

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.