JKLayout adding Meta Tracking

This commit is contained in:
Seth Call 2026-01-16 16:44:46 -06:00
parent fae16c7483
commit 71d8571eb9
2 changed files with 86 additions and 3 deletions

View File

@ -0,0 +1,81 @@
/**
* meta_tracking.js
* A standalone module to capture and persist Meta attribution signals (fbclid, _fbp) in cookies.
*
* Logic adapted from web/app/assets/javascripts/meta_tracking.js for React environment.
* - Checks URL for `fbclid` and sets `_fbc` cookie.
* - Checks for `_fbp` cookie; if missing, generates and sets it.
*/
const MetaTracking = {
init: function () {
const location = window.location;
this.handleFbc(location.search);
this.handleFbp();
},
// 1. Parsing and storing _fbc (Click ID)
handleFbc: function (searchParams) {
const fbclid = this.getQueryParam('fbclid', searchParams);
if (fbclid) {
const version = 'fb';
const subdomainIndex = 1; // 1 = example.com
const creationTime = new Date().getTime(); // Unix timestamp in ms
// Format: fb.1.timestamp.id
const fbcValue = `${version}.${subdomainIndex}.${creationTime}.${fbclid}`;
this.setCookie('_fbc', fbcValue, 90);
}
},
// 2. Handling _fbp (Browser ID)
handleFbp: function () {
if (!this.getCookie('_fbp')) {
const version = 'fb';
const subdomainIndex = 1;
const creationTime = new Date().getTime();
const randomInt = Math.floor(Math.random() * 10000000000); // 10-digit random number
// Format: fb.1.timestamp.randomDigits
const fbpValue = `${version}.${subdomainIndex}.${creationTime}.${randomInt}`;
this.setCookie('_fbp', fbpValue, 90);
}
},
// Helper: Get query param by name
getQueryParam: function (name, search) {
name = name.replace(/[\[]/, '\\[').replace(/[\]]/, '\\]');
const regex = new RegExp('[\\?&]' + name + '=([^&#]*)');
const results = regex.exec(search);
return results === null ? '' : decodeURIComponent(results[1].replace(/\+/g, ' '));
},
// Helper: Set cookie
setCookie: function (name, value, days) {
let expires = "";
if (days) {
const date = new Date();
date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
expires = "; expires=" + date.toUTCString();
}
// Ensure path is root and domain is included if needed (defaults to current host)
document.cookie = name + "=" + (value || "") + expires + "; path=/";
},
// Helper: Get cookie
getCookie: function (name) {
const nameEQ = name + "=";
const ca = document.cookie.split(';');
for (let i = 0; i < ca.length; i++) {
let c = ca[i];
while (c.charAt(0) === ' ') c = c.substring(1, c.length);
if (c.indexOf(nameEQ) === 0) return c.substring(nameEQ.length, c.length);
}
return null;
}
};
export default MetaTracking;

View File

@ -1,4 +1,4 @@
import React, {useEffect} from 'react'; import React, { useEffect } from 'react';
import { Route, Switch } from 'react-router-dom'; import { Route, Switch } from 'react-router-dom';
import { toast, ToastContainer } from 'react-toastify'; import { toast, ToastContainer } from 'react-toastify';
import { CloseButton, Fade } from '../components/common/Toast'; import { CloseButton, Fade } from '../components/common/Toast';
@ -8,6 +8,7 @@ import ErrorLayout from './ErrorLayout';
import BuildMeta from "./JKBuildMeta"; import BuildMeta from "./JKBuildMeta";
import loadable from '@loadable/component'; import loadable from '@loadable/component';
import MetaTracking from "../helpers/MetaTracking";
const AuthBasicLayout = loadable(() => import('./JKAuthBasicLayout')); const AuthBasicLayout = loadable(() => import('./JKAuthBasicLayout'));
const PublicLayout = loadable(() => import('./JKPublicLayout')); const PublicLayout = loadable(() => import('./JKPublicLayout'));
@ -15,6 +16,7 @@ const Layout = () => {
useEffect(() => { useEffect(() => {
AuthBasicLayout.preload(); AuthBasicLayout.preload();
PublicLayout.preload(); PublicLayout.preload();
MetaTracking.init();
//see if there is affiliate in query string and save it as cookie //see if there is affiliate in query string and save it as cookie
const urlParams = new URLSearchParams(window.location.search); const urlParams = new URLSearchParams(window.location.search);