/* Lighom User Data Enricher v5 - RAW values to fbq init (fbq auto-hashes), hashed for CAPI dataLayer path, email persistence to cookie/localStorage, format per Meta spec */
(function(){
if (window.__lighom_userdata_enricher_v5) return;
window.__lighom_userdata_enricher_v5 = true;
var PIXEL_ID = "479292381165317";
var COOKIE_EMAIL = "_lighom_user_em";
var rawCache = {};
var hashedCache = {};
var pending = false;
var lastFbqInit = "";
var EVENT_NAMES = /^(purchase|add_payment_info|begin_checkout|add_to_cart|complete_registration|search|view_item|view_item_list|view_category|view_content|initiate_checkout|search_submitted)$/i;
var GTAG_ECOM = /^(view_item|view_item_list|add_to_cart|begin_checkout|add_payment_info|add_shipping_info|search|select_item|select_promotion|view_promotion|remove_from_cart|view_cart)$/i;
function ck(name){ var m = document.cookie.match(new RegExp("(?:^|;\\s*)" + name + "=([^;]+)")); return m ? decodeURIComponent(m[1]) : ""; }
function setCk(name, val, days){ try { document.cookie = name + "=" + encodeURIComponent(val) + ";path=/;max-age=" + (days*86400) + ";SameSite=Lax"; } catch(e){} }
/* Format per Meta spec: lowercase + trim, then per-field cleaning */
function norm(field, value){
if (!value) return "";
value = String(value).trim().toLowerCase();
if (field === "em") return value;
if (field === "ph") return value.replace(/[\s\-()]/g, ""); /* keep + and digits, E.164 */
if (field === "zp") return value.replace(/\s/g, "").substring(0, 5); /* US: first 5 chars */
if (field === "country") return value.replace(/\s/g, "").substring(0, 2); /* 2-letter ISO */
if (field === "ct" || field === "st") return value.replace(/\s/g, "");
return value;
}
function sha256(s){
if (!s || !window.crypto || !crypto.subtle) return Promise.resolve("");
try {
return crypto.subtle.digest("SHA-256", new TextEncoder().encode(s)).then(function(buf){
return Array.from(new Uint8Array(buf)).map(function(b){ return b.toString(16).padStart(2,"0"); }).join("");
});
} catch(e){ return Promise.resolve(""); }
}
function getInputValue(selector){
var els = document.querySelectorAll(selector);
for (var i = 0; i < els.length; i++) {
var el = els[i];
var v = el.value || (el.options && el.selectedIndex >= 0 ? (el.options[el.selectedIndex].dataset.code || el.options[el.selectedIndex].text) : "");
if (v && v.trim()) return v.trim();
}
return "";
}
function scanDOM(){
var found = false;
/* email — DOM input or persisted cookie */
var em = getInputValue("input[type=\"email\"], input[name*=\"email\" i], input[id*=\"email\" i], input[autocomplete=\"email\"]");
if (!em) em = ck(COOKIE_EMAIL) || (function(){ try { return localStorage.getItem(COOKIE_EMAIL) || ""; } catch(e){ return ""; } })();
if (em && /\S+@\S+\.\S+/.test(em) && rawCache.em !== em) {
rawCache.em = em; found = true;
try { setCk(COOKIE_EMAIL, em, 365); localStorage.setItem(COOKIE_EMAIL, em); } catch(e){}
}
var ph = getInputValue("input[type=\"tel\"], input[name*=\"phone\" i], input[id*=\"phone\" i], input[name*=\"mobile\" i], input[autocomplete=\"tel\"]");
if (ph && rawCache.ph !== ph) { rawCache.ph = ph; found = true; }
var fn = getInputValue("input[name*=\"first_name\" i], input[name*=\"firstName\" i], input[id*=\"first_name\" i], input[autocomplete=\"given-name\"]");
if (fn && rawCache.fn !== fn) { rawCache.fn = fn; found = true; }
var ln = getInputValue("input[name*=\"last_name\" i], input[name*=\"lastName\" i], input[id*=\"last_name\" i], input[autocomplete=\"family-name\"]");
if (ln && rawCache.ln !== ln) { rawCache.ln = ln; found = true; }
var ct = getInputValue("input[name*=\"city\" i], input[id*=\"city\" i], input[autocomplete=\"address-level2\"]");
if (ct && rawCache.ct !== ct) { rawCache.ct = ct; found = true; }
var st = getInputValue("input[name*=\"province\" i], input[name*=\"state\" i], input[id*=\"province\" i], select[name*=\"province\" i], select[name*=\"state\" i], input[autocomplete=\"address-level1\"], select[autocomplete=\"address-level1\"]");
if (st && rawCache.st !== st) { rawCache.st = st; found = true; }
var zp = getInputValue("input[name*=\"postal\" i], input[name*=\"zip\" i], input[name*=\"postcode\" i], input[autocomplete=\"postal-code\"]");
if (zp && rawCache.zp !== zp) { rawCache.zp = zp; found = true; }
var country = getInputValue("select[name*=\"country\" i], input[name*=\"country\" i], input[autocomplete=\"country\"]");
if (country && rawCache.country !== country) { rawCache.country = country; found = true; }
var ps = window.__PRELOAD_STATE__;
var uid = (ps && ps.user && (ps.user.id || ps.user.userId)) || (ps && ps.userInfo && ps.userInfo.userId) || (ps && ps.orders && ps.orders.buyerInfo && ps.orders.buyerInfo.buyerId);
if (uid && rawCache.external_id !== String(uid)) { rawCache.external_id = String(uid); found = true; }
if (found && !pending) updateData();
return found;
}
function updateData(){
pending = true;
var keys = Object.keys(rawCache);
/* Build normalized RAW for fbq browser pixel (fbq auto-hashes) */
var normRaw = {};
keys.forEach(function(k){ var v = norm(k, rawCache[k]); if (v) normRaw[k] = v; });
/* Build SHA-256 hashed for server CAPI dataLayer path */
Promise.all(keys.map(function(k){ return sha256(norm(k, rawCache[k])); })).then(function(hashes){
var newHashed = {};
keys.forEach(function(k, i){ if (hashes[i]) newHashed[k] = hashes[i]; });
hashedCache = newHashed;
window.__lighom_user_data_hashed = newHashed;
window.__lighom_user_data_raw = rawCache;
window.__lighom_user_data_normraw = normRaw;
pending = false;
/* v5 FIX: pass RAW (normalized) to fbq init - fbq auto-hashes for browser pixel matching */
if (typeof window.fbq === "function" && Object.keys(normRaw).length) {
var sig = JSON.stringify(normRaw);
if (sig !== lastFbqInit) {
lastFbqInit = sig;
try { window.fbq("init", PIXEL_ID, normRaw); } catch(e){}
}
}
});
}
function buildUserData(existing){
var ud = Object.assign({}, existing || {});
if (rawCache.em && !ud.email_address) ud.email_address = rawCache.em;
if (rawCache.ph && !ud.phone_number) ud.phone_number = rawCache.ph;
if (rawCache.fn && !ud.first_name) ud.first_name = rawCache.fn;
if (rawCache.ln && !ud.last_name) ud.last_name = rawCache.ln;
if (rawCache.ct && !ud.city) ud.city = rawCache.ct;
if (rawCache.st && !ud.region) ud.region = rawCache.st;
if (rawCache.zp && !ud.postal_code) ud.postal_code = rawCache.zp;
if (rawCache.country && !ud.country) ud.country = rawCache.country;
if (rawCache.external_id && !ud.user_id) ud.user_id = rawCache.external_id;
if (hashedCache.em && !ud.em) ud.em = hashedCache.em;
if (hashedCache.ph && !ud.ph) ud.ph = hashedCache.ph;
if (hashedCache.fn && !ud.fn) ud.fn = hashedCache.fn;
if (hashedCache.ln && !ud.ln) ud.ln = hashedCache.ln;
if (hashedCache.ct && !ud.ct) ud.ct = hashedCache.ct;
if (hashedCache.st && !ud.st) ud.st = hashedCache.st;
if (hashedCache.zp && !ud.zp) ud.zp = hashedCache.zp;
if (hashedCache.external_id && !ud.external_id) ud.external_id = hashedCache.external_id;
return ud;
}
function enrich(arg){
if (!arg || !arg.event || !EVENT_NAMES.test(arg.event)) return arg;
arg.user_data = buildUserData(arg.user_data);
if (!arg.fbp) arg.fbp = ck("_fbp");
if (!arg.fbc) arg.fbc = ck("_fbc");
if (!arg.epik) arg.epik = ck("_epik");
return arg;
}
function bridgeGtag(arg){
if (!arg || arg["0"] !== "event" || !GTAG_ECOM.test(arg["1"])) return null;
var eventName = arg["1"];
var data = arg["2"] || {};
if (data.send_to) return null;
var bridged = {
event: eventName,
event_id: data.event_id,
ecommerce: {
value: data.value,
currency: data.currency,
items: data.items,
transaction_id: data.transaction_id,
content_ids: data.content_ids || (data.items ? data.items.map(function(it){ return it.item_id || it.id; }).filter(Boolean) : undefined),
content_type: data.content_type || (data.items && data.items.length ? "product" : undefined),
num_items: data.items ? data.items.length : undefined
}
};
return bridged;
}
function start(){
scanDOM();
if (!window.dataLayer) window.dataLayer = [];
var origPush = window.dataLayer.push.bind(window.dataLayer);
window.dataLayer.push = function(arg){
if (arg && arg.event && EVENT_NAMES.test(arg.event)) {
scanDOM();
enrich(arg);
return origPush(arg);
}
var bridged = bridgeGtag(arg);
if (bridged) {
scanDOM();
enrich(bridged);
var orig = origPush(arg);
try { setTimeout(function(){ origPush(bridged); }, 0); } catch(e){}
return orig;
}
return origPush(arg);
};
document.addEventListener("blur", scanDOM, true);
document.addEventListener("change", scanDOM, true);
var inputTimer;
document.addEventListener("input", function(){ clearTimeout(inputTimer); inputTimer = setTimeout(scanDOM, 300); }, true);
setInterval(scanDOM, 2000);
var existing = window.dataLayer.slice();
setTimeout(function(){
existing.forEach(function(item){
var b = bridgeGtag(item);
if (b) { enrich(b); origPush(b); }
});
}, 100);
}
if (document.readyState === "loading") document.addEventListener("DOMContentLoaded", start);
else start();
})();
ENJOY 10% OFF YOUR FIRST ORDER
Free International Shipping
30-Day Satisfaction Guarantee