pixel: add ensure fbc fallback
This commit is contained in:
88
src/lib/metapixel/fbc.ts
Normal file
88
src/lib/metapixel/fbc.ts
Normal file
@@ -0,0 +1,88 @@
|
||||
import log from 'loglevel';
|
||||
|
||||
export type EnsureFbcOptions = {
|
||||
days?: number; // cookie lifetime, default 180
|
||||
domain?: string; // optional cookie domain
|
||||
sameSite?: 'Lax' | 'Strict' | 'None'; // default Lax
|
||||
secure?: boolean; // default inferred from location.protocol === 'https:'
|
||||
pixelLoaded?: boolean; // if true, skip manual set and let Pixel handle it
|
||||
};
|
||||
|
||||
function getParam(name: string): string | undefined {
|
||||
const params = new URLSearchParams(location.search);
|
||||
const v = params.get(name);
|
||||
return v || undefined;
|
||||
}
|
||||
|
||||
function getCookie(name: string): string | undefined {
|
||||
return document.cookie
|
||||
.split('; ')
|
||||
.find((c) => c.startsWith(name + '='))
|
||||
?.split('=')[1];
|
||||
}
|
||||
|
||||
function setCookie(
|
||||
name: string,
|
||||
value: string,
|
||||
{
|
||||
days = 180,
|
||||
domain,
|
||||
sameSite = 'Lax',
|
||||
secure
|
||||
}: Pick<EnsureFbcOptions, 'days' | 'domain' | 'sameSite' | 'secure'> = {}
|
||||
) {
|
||||
const d = new Date();
|
||||
d.setTime(d.getTime() + days * 864e5);
|
||||
const parts = [
|
||||
`${name}=${encodeURIComponent(value)}`,
|
||||
`expires=${d.toUTCString()}`,
|
||||
'path=/',
|
||||
`SameSite=${sameSite}`
|
||||
];
|
||||
if (domain) parts.push(`domain=${domain}`);
|
||||
const isSecure = secure ?? location.protocol === 'https:';
|
||||
if (isSecure) parts.push('Secure');
|
||||
document.cookie = parts.join('; ');
|
||||
}
|
||||
|
||||
function isValidFbc(value: string | undefined): boolean {
|
||||
if (!value) return false;
|
||||
// Expect "fb.1.<unix>.<fbclid>"
|
||||
if (!value.startsWith('fb.1.')) return false;
|
||||
const parts = value.split('.');
|
||||
return parts.length >= 4 && /^\d+$/.test(parts[2]) && parts[3].length > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure _fbc cookie exists when landing URL contains fbclid.
|
||||
* Call after consent. If pixelLoaded is true, it skips manual setting.
|
||||
*/
|
||||
export function ensureFbc(options: EnsureFbcOptions = {}) {
|
||||
try {
|
||||
const { pixelLoaded = false, ...cookieOpts } = options;
|
||||
|
||||
if (pixelLoaded) throw new Error('Pixel loaded, skipping manual _fbc set'); // Let the Pixel set _fbc if it’s active
|
||||
|
||||
const fbclid = getParam('fbclid');
|
||||
if (!fbclid) throw new Error('No fbclid param present');
|
||||
|
||||
const existing = getCookie('_fbc');
|
||||
if (isValidFbc(existing)) throw new Error('_fbc cookie already present and valid');
|
||||
|
||||
const ts = Math.floor(Date.now() / 1000);
|
||||
const fbc = `fb.1.${ts}.${fbclid}`;
|
||||
setCookie('_fbc', fbc, cookieOpts);
|
||||
log.debug('[ensureFbc] Set _fbc cookie:', fbc);
|
||||
} catch (e) {
|
||||
log.debug('[ensureFbc]', (e as Error).message);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper to read both _fbp and _fbc for your CAPI payload.
|
||||
*/
|
||||
export function getFbpFbc(): { fbp?: string; fbc?: string } {
|
||||
const fbp = getCookie('_fbp');
|
||||
const fbc = getCookie('_fbc');
|
||||
return { fbp, fbc };
|
||||
}
|
||||
Reference in New Issue
Block a user