1// ============================================================= 2// Matomo + GTM Form Data Push (fixed and unified version) 3// ------------------------------------------------------------- 4// - Ensures content_type is set (from data OR URL fallback) 5// - Adds "event" to every dataLayer push (GTM can trigger) 6// - Adds nested payload.event for templates expecting payload.* 7// - Normalizes subscribe_status to "Yes"/"No" 8// - Lowercases email before storing 9// - Pushes Matomo userId (plain email) + Identity Status (new/known) 10// ============================================================= 11 12// Helper: map current path to a normalized content_type 13function deriveContentTypeFromPath () { 14 var p = (location.pathname || '').toLowerCase() 15 16 // White paper 17 if (/^\/research\/wp(\/|$)/.test(p)) return 'whitepaper' 18 19 // Infographics 20 if (/^\/research\/infographics(\/|$)/.test(p)) return 'infographic' 21 22 // Podcast 23 if (/^\/research\/podcast(\/|$)/.test(p)) return 'podcast' 24 25 // Discussion Guide (DG) 26 if (/^\/global-trade\/discussion-guides(\/|$)/.test(p)) return 'discu
26ssion_guide' 27 28 // No match 29 return '' 30} 31 32window.handlePageContentForm = () => { 33 if (window.__HF_HUBSPOT_FORM_DLV_DONE) return 34 console.log("Handling page content form for Matomo") 35 36 try { 37 const raw = localStorage.getItem("whitePaperLastSubmission") 38 if (!raw) return 39 40 let d = {} 41 try { d = JSON.parse(raw) || {} } catch (e) { } 42 43 const query = (location.search || "").replace(/^\?/, "").split("&") 44 const utm = function (k) { 45 for (let i = 0;i < query.length;i++) { 46 const kv = query[i].split("=") 47 if (decodeURIComponent(kv[0] || "") === k) return decodeURIComponent(kv[1] || "") 48 } 49 return d[k] || "" 50 } 51 52 const pick = function (...args) { 53 for (const k of args) { 54 if (d && d[k] != null && d[k] !== "") return String(d[k]) 55 } 56 return "" 57 } 58 59 const yesNo = function (v) { 60 if (v == null || v === "") return "" 61 if (typeof v === "boolean") return v ? "Yes" : "No" 62 const s = String(v).toLowerCase() 63 if (["true", "yes", "1"].includes(s)) return "Yes" 64 if (["false", "no", "0"].includes(s)) return "No" 65 return "" 66 } 67 68 const email = (pick("email", "userEmail", "mail") || "").trim().toLowerCase() 69 70 // â ensure content_type exists (from storage OR URL) 71 const contentType = 72 pick("content_type", "form_type", "type") || deriveContentTypeFromPath() 73 74 const base = { 75 content_type: contentType, // <- now guaranteed when URL matches 76 form_name: pick("form_name", "whitepaperTitle", "formTitle", "formName", "title", "name") || document.title, 77 asset_id: pick("asset_id", "assetId", "assetID", "id", "slug"), 78 asset_url: location.href, 79 page: location.pathname, 80 submitted_at: new Date().toISOString(), 81 82 author: pick("author"), 83 publish_date: pick("publish_date", "publishDate", "date"), 84 topics: pick("topics", "topic", "tags"), 85 86 email: email, 87 organization: pick("organization", "company", "org", "employer", "institution"), 88 job_title: pick("job_title", "job", "jobtitle", "jobTitle", "occupation", "role", "position", "title"), 89 country: pick("country", "country_code", "location", "countryCode", "country___region"), 90 sector: pick("sector", "industry", "vertical", "sector__emerson_test_"), 91 subscribe_status: (d.hasOwnProperty("subscribe_status") 92 ? yesNo(d.subscribe_status) 93 : (d.hasOwnProperty("subscribe") ? yesNo(d.subscribe) : "")), 94 95 utm_source: utm("utm_source"), 96 utm_medium: utm("utm_medium"), 97 utm_campaign: utm("utm_campaign"), 98 } 99 100 // Push top-level event + nested payload.event 101 window.dataLayer = window.dataLayer || [] 102 const dlObj = Object.assign({ event: "hf_asset_form_submit" }, base, { 103 payload: Object.assign({ event: "hf_asset_form_submit" }, base), 104 }) 105 window.dataLayer.push(dlObj) 106 console.log("[dataLayer.push][pageContent]", dlObj) 107 108 window.__HF_HUBSPOT_FORM_DLV_DONE = true 109 110 // Optional: Matomo known/new user tracking 111 if (email) { 112 const prev = (localStorage.getItem("matomo_user_id") || "").toLowerCase() 113 const status = prev ? "known" : "new" 114 window._paq = window._paq || [] 115 _paq.push(["setUserId", email]) 116 _paq.push(["trackEvent", "Identity", "Status", status]) 117 try { localStorage.setItem("matomo_user_id", email) } catch (e) { } 118 } 119 } catch (err) { 120 console.warn("[DLV populate error]", err) 121 } 122} 123 124 125window.handleDiscussionGuideForm = ($form) => { 126 console.log("Handling discussion guide form for Matomo") 127 console.log($form) 128 const raw = localStorage.getItem("whitePaperLastSubmission") 129 let d = {} 130 try { d = JSON.parse(raw) || {} } catch (e) { } 131 const pick = function (...args) { 132 for (const k of args) { 133 if (d && d[k] != null && d[k] !== "") return String(d[k]) 134 } 135 return "" 136 } 137 138 if (window.__HF_HUBSPOT_FORM_DISCUSSION_GUIDE_DONE) return 139 const formEl = 140 ($form && ($form.get && $form.get(0))) || 141 ($form && $form[0]) || 142 $form || 143 document.getElementById("discussion-form") 144 145 function get (name) { 146 // FIXED selector: 147 const el = formEl && formEl.querySelector(`[name="${name}"]`) 148 return el ? (el.value || "").trim() : "" 149 } 150 151 function pickSelectVal (sel) { 152 const el = formEl && formEl.querySelector(sel) 153 let val = el ? (el.value || "").trim() : "" 154 if (/please select/i.test(val)) val = "" 155 return val 156 } 157 const title = localStorage.getItem("discussion-guide-active-resource-title") 158 // If this form should remain as a separate type, keep 'discussion_guide' 159 // (If you want it to be categorized like the others, swap to deriveContentTypeFromPath()) 160 const content_type = "discussion_guide" 161 162 const form_name = get("resource_title") || title || "Discussion Guide" 163 const asset_id = get("resource_id") || location.pathname.split("/").filter(
163Boolean).pop() || title || "" 164 const topics = get("resource_topic") || pick("topics", "topic", "tags") || get("content_topic__form_submission_field_") || pick("content_topic__form_submission_field_") || "" 165 166 const author = 167 (document.querySelector('meta[name="author"]') || {}).content || 168 get("author__form_submission_field_") || 169 pick("author__form_submission_field_") || 170 (document.querySelector('a[href^="/profiles/experts-contributors/"]') || {}).textContent || 171 "" 172 const publish_date = 173 (document.querySelector('meta[property="article:published_time"]') || {}).content || 174 (document.querySelector('meta[itemprop="datePublished"]') || {}).content || 175 get("publish_date__form_submission_field_") || 176 pick("publish_date__form_submission_field_", "publish_date", "publishDate", "date") || 177 "" 178 179 const usp = new URLSearchParams(location.search) 180 const utm_source = usp.get("utm_source") || "" 181 const utm_medium = usp.get("utm_medium") || "" 182 const utm_campaign = usp.get("utm_campaign") || "" 183 184 const email = (get("email") || get("Email") || get("EMAIL") || pick("email", "userEmail", "mail") || "").trim().toLowerCase() 185 const organization = get("organization") || get("company") || pick("organization", "company", "org", "employer", "institution") 186 const job_title = get("job_title") || get("jobtitle") || get("title") || pick("job_title", "jobtitle") 187 const country = pickSelectVal('select[name*="country" i], select[id*="country" i]') || get("country") || pick("country", "country_code", "location", "countryCode", "country___region") 188 const sector = pickSelectVal('select[name*="sector" i], select[id*="sector" i]') || get("sector") || get("sector__emerson_test_") || pick("sector", "industry", "vertical", "sector__emerson_test_") 189 190 const subscribeEl = 191 formEl && 192 (formEl.querySelector('input[type="checkbox"][name*="subscribe" i]') || 193 formEl.querySelector('input[type="checkbox"][id*="subscribe" i]')) 194 const subscribe_status = subscribeEl && subscribeEl.checked ? "Yes" : "No" 195 196 // Push top-level + nested payload.event 197 window.dataLayer = window.dataLayer || [] 198 const base = { 199 content_type, 200 form_name, 201 asset_id, 202 asset_url: location.href, 203 author: (author || "").trim(), 204 publish_date, 205 topics, 206 page: location.pathname, 207 submitted_at: new Date().toISOString(), 208 email, 209 organization, 210 job_title, 211 country, 212 sector, 213 subscribe_status, 214 utm_source, 215 utm_medium, 216 utm_campaign, 217 } 218 const dlObj = Object.assign({ event: "hf_asset_form_submit" }, base, { 219 payload: Object.assign({ event: "hf_asset_form_submit" }, base), 220 }) 221 window.dataLayer.push(dlObj) 222 console.log("[dataLayer.push][discussionGuide]", dlObj) 223 224 // Optional: Matomo userId tracking 225 if (email) { 226 const prev = (localStorage.getItem("matomo_user_id") || "").toLowerCase() 227 const status = prev ? "known" : "new" 228 window._paq = window._paq || [] 229 _paq.push(["setUserId", email]) 230 _paq.push(["trackEvent", "Identity", "Status", status]) 231 try { localStorage.setItem("matomo_user_id", email) } catch (e) { } 232 } 233 window.__HF_HUBSPOT_FORM_DISCUSSION_GUIDE_DONE = true 234}
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.