1import { Controller } from "@hotwired/stimulus" 2 3// Site-wide first-party page-view beacon (CRM) â one async POST per public 4// page load: path + referrer. Lands in Public::PageViewsController#create as 5// a PageView row keyed on the yw_visitor_token cookie, so anonymous reading 6// history retro-attaches to the person the moment they identify. 7// 8// Attached to a hidden element in the layout (shared/_page_view_beacon), so 9// Turbo navigations re-connect and each visit fires once. Delivery mirrors 10// engagement_beacon_controller: sendBeacon-first, keepalive-fetch fallback, 11// failures swallowed â tracking never breaks the page. 12// 13// Privacy: only location.pathname is sent (no query string â the server 14// strips again as belt + braces). Referrer is document.referrer on a fresh 15// load, the previous in-app path on Turbo navigations. 16let lastTrackedPath = null 17 18export default class extends Controller { 19 static values = { endpoint: String } 20 21 connect() { 22 // Turbo cache previews render momentarily before the real response â 23 // don't double-fire. 24 if (document.documentElement.hasAttribute("data-turbo-preview")) return 25 26 const path = window.location.pathname 27 if (path === lastTrackedPath) return // Turbo restore of the same page 28 29 const referrer = lastTrackedPath || document.referrer || "" 30 lastTrackedPath = path 31 this.post(path, referrer) 32 } 33 34 post(path, referrer) { 35 if (!this.endpointValue) return 36 37 const body = new FormData() 38 body.append("path", path) 39 if (referrer) body.append("referrer", referrer) 40 41 let sent = false 42 if (navigator.sendBeacon) { 43 try { 44 sent = navigator.sendBeacon(this.endpointValue, body) 45 } catch (_e) { 46 sent = false 47 } 48 } 49 if (!sent) { 50 fetch(this.endpointValue, { 51 method: "POST", 52 body, 53 credentials: "same-origin", 54 keepalive: true 55 }).catch(() => { /* best-effort */ }) 56 } 57 } 58};
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.