PageSourceSearch

https://betterstack.com/assets/common/site_settings_bootstrap-c104a0e6.js

js betterstack.com collected 2026-10-09 23:01:05 UTC 2,906 bytes, 107 lines download raw bytes

1// Cookie consent auto-grant for non-EU users
2// Handles: country detection, consent auto-granting, event dispatching
3// Runs on all pages to ensure tracking initializes everywhere
4
5// Export utilities for reuse by banner module
6export const CONSENT_COOKIE_NAME = 'cookie_consent'
7
8export async function fetchCountryData() {
9  const response = await fetch('/api/consent-country', {
10    method: 'GET',
11    credentials: 'same-origin',
12    headers: {
13      'Accept': 'application/json',
14    }
15  })
16
17  if (!response.ok) {
18    throw new Error(`Country API returned ${response.status}`)
19  }
20
21  return response.json()
22}
23
24export function getCookie(name) {
25  const nameEQ = `${name}=`
26  const cookies = document.cookie.split(';')
27  for (let cookie of cookies) {
28    cookie = cookie.trim()
29    if (cookie.indexOf(nameEQ) === 0) {
30      return cookie.substring(nameEQ.length)
31    }
32  }
33  return null
34}
35
36export function dispatchConsentEvent(consentType) {
37  const event = new CustomEvent('cookie-consent-granted', {
38    detail: { consentType }
39  })
40  document.dispatchEvent(event)
41}
42
43class SiteSettingsBootstrap {
44  constructor() {
45    this.isInitialized = false
46  }
47
48  init() {
49    if (this.isInitialized) return
50    this.isInitialized = true
51
52    const existingConsent = getCookie(CONSENT_COOKIE_NAME)
53
54    // If user already has consent preference, respect it
55    if (existingConsent === 'accept_all' || existingConsent === 'accept_required' || existingConsent === 'denied') {
56      if (existingConsent === 'accept_all') {
57        dispatchConsentEvent('accept_all')
58      } else if (existingConsent === 'accept_required') {
59        dispatchConsentEvent('accept_required')
60      }
61      return
62    }
63
64    // No existing consent - check country and auto-grant for non-EU
65    this.checkCountryAndAutoGrant()
66  }
67
68  async checkCountryAndAutoGrant() {
69    try {
70      let countryData = window.countryData
71
72      // Fetch country data if not cached (allows VPN testing)
73      if (!countryData) {
74        countryData = await fetchCountryData()
75        window.countryData = countryData
76      }
77
78      // Auto-grant consent for non-EU users
79      if (!countryData.eu) {
80        dispatchConsentEvent('accept_all')
81      }
82      // For EU users: do nothing, let banner handle it
83    } catch (error) {
84      // On error, do nothing (assume EU, let banner show)
85    }
86  }
87}
88
89// Initialize on every page load and Turbo navigation
90function initializeConsentAutoGrant() {
91  if (!window.cookieConsentAutoGrant) {
92    window.cookieConsentAutoGrant = new SiteSettingsBootstrap()
93  }
94  window.cookieConsentAutoGrant.init()
95}
96
97// Initial load
98if (document.readyState === 'loading') {
99  document.addEventListener('DOMContentLoaded', initializeConsentAutoGrant)
100} else {
101  initializeConsentAutoGrant()
102}
103
104// Handle Turbo navigation
105document.addEventListener('turbo:load', initializeConsentAutoGrant)
106
107export default SiteSettingsBootstrap

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.