Introduction Last updated: May 24 - 2025

Overview

This web helper library is designed to streamline the collection of key user, client, and page-level data for marketing and analytics purposes. By providing a lightweight and extensible JavaScript toolkit, it enables developers and marketers to easily gather information such as browser details, device type, screen resolution, geolocation, referral source, UTM parameters, and page metadata. The goal is to provide meaningful insights into user behavior and campaign performance without requiring heavy third-party dependencies or bloated tracking scripts.

Purpose

Whether you're building custom analytics dashboards, personalizing user experiences, or enhancing conversion tracking, this library offers a flexible foundation to support your data needs. It is ideal for developers looking to maintain control over their data pipelines while reducing reliance on third-party tracking services. With a focus on privacy compliance and performance, the library ensures that you can collect the data you need efficiently and responsibly.

Output structure

This is a real-time example of the (not all, as some code like integrations are only visible when the corresponding third-party call is found) object output that can be invoked from any JS code present in the page.
All of the data present hangs from parent window.mktpacket object. which is split in the following structure:

  • data contains the output of different sources packed in this unique object part organized in:
    • client collects the data related to user device and browser. It fetches battery, network and screen information.
    • page is related to the page loaded, basics like title, url, metadata, and more advanced like click count on each element or if a form present in-page has been already submitted.
    • user has all data about the user behaviour and unique information. You can check if an user is a potential bot, has adblock enabled, if it has already visited the website or what was his first page seen.
    • Integration modules like ga, abtasty, onetrust when the corresponding 3rd-party code is present.
  • ctrl contains config data and API responses for logging and debugging. Licence information and last request time to the API.
  • func helds the callable functions if any of the data needs to be updated in a specific moment, or need a refresh. All of the available functions are listed on Data Functions section

Installation

The installation process is as easy as including a JS script file into your <header> tag, recommending it being the last script to prevent resource-blockage.

You can use either the jsdelivr version directly from github repository:

<header>
  <script src="https://cdn.jsdelivr.net/gh/codebakersdev/mktpacket@master/main.js" key="free-version" gtag=""></script>
</header>

Or our selfhosted version under codebakers.dev domain:

<header>
  <script src="https://codebakers.dev/mktpacket/main.js" key="free-version" gtag=""></script>
</header>

Script Configuration

The script, as of now, accepts 2 parameters when loading:

  • key is the API Key that enables the PRO features, the key is linked to 1 domain each, if the key is free-version or it's missing, the PRO features are not loaded into the Object.

Note

PRO features will be available under free-version licence key until January 6th 2026, while we beta-test the library and ultimate the PRO features for best experience.

All of the PRO features are marked with "PRO" ribbon in the function list section.

  • gtag is the Google Tag Manager tag necessary to enable features like the reading of clientID and sessionID linked to Google Analytics.

Data Functions

This section describes each one of the functions present in the JS library, with the technical and functional explanation, and practical examples of usage.

All of the functions are inside the mktpacket.func object, so for calling a function you will need to include the part before funcion name.

The functions itself don't return any data when called, only the data inside data object corresponding to the function.

getClient functions

This functions are related to device, browser, operating system, network, etc. of the accessing person. It uses mostly data from document, window and navigator.

mktpacket.func.getClientIsTouchscreen()

A function that outputs true or false depending if the screen has touch support.

Data persists: No

Output: boolean

Default value: false

getClientIsTouchscreen : function() {
  mktpacket.data.client.is_touchscreen = ('ontouchstart' in window) || (navigator.maxTouchPoints > 0) || (navigator.msMaxTouchPoints > 0) ? true : false;
}

mktpacket.func.getClientIsMobile()

A function that detects if the client device is a mobile device by using navigator.userAgentData when available, or by matching known mobile user-agent strings.

Data persists: No

Output: boolean

Default value: false

getClientIsMobile: function() {
  if (navigator.userAgentData && 'mobile' in navigator.userAgentData) {
    mktpacket.data.client.is_mobile = navigator.userAgentData.mobile;
  } else {
    var ua = navigator.userAgent.toLowerCase();
    mktpacket.data.client.is_mobile = /iphone|ipod|android|blackberry|iemobile|opera mini/.test(ua);
  }
}

mktpacket.func.getClientScreenOrientation()

A function that detects the screen's current orientation using screen.orientation.type and updates it every second.

Data persists: No

Output: string (e.g., portrait-primary, landscape-primary)

Default value: undefined

getClientScreenOrientation: function() {
  mktpacket.data.client.screen_orientation = screen.orientation.type;
  setTimeout(window.mktpacket.func.getClientScreenOrientation, 1000);
}

mktpacket.func.getClientPlatform()

A function that detects the client's platform (operating system or device) by matching patterns in the navigator.userAgent string.

Data persists: No

Output: string (e.g., android, iphone, windows, linux, zebra)

Default value: "unknown"

getClientPlatform: function() {
  const userAgent = navigator.userAgent;
  const platforms = [
    { name: 'android', pattern: /Android/i },
    { name: 'iphone', pattern: /iPhone/i },
    { name: 'ipad', pattern: /iPad/i },
    { name: 'ipod', pattern: /iPod/i },
    { name: 'windows', pattern: /IEMobile|Windows/i },
    { name: 'macos', pattern: /Macintosh/i },
    { name: 'chromeos', pattern: /CrOS/i },
    { name: 'linux', pattern: /Linux/i },
    { name: 'blackberry', pattern: /BlackBerry/i },
    { name: 'bluebird', pattern: /EF500/i },
    { name: 'datalogic', pattern: /DL-AXIS/i },
    { name: 'honeywell', pattern: /CT50/i },
    { name: 'zebra', pattern: /TC70|TC55/i }
  ];
  let client_platform = 'unknown';
  for (const platform of platforms) {
    if (platform.pattern.test(userAgent)) {
      client_platform = platform.name;
      break;
    }
  }
  mktpacket.data.client.platform = client_platform;
}

mktpacket.func.getClientBrowserName()

A function that detects the client's browser name by checking for known identifiers within the navigator.userAgent string.

Data persists: No

Output: string (e.g., chrome, firefox, safari, edge, opera, vivaldi)

Default value: "unknown"

getClientBrowserName: function() {
  const userAgent = navigator.userAgent;
  const browsers = [
    { name: 'chrome', patterns: ['Chrome'] },
    { name: 'firefox', patterns: ['Firefox'] },
    { name: 'safari', patterns: ['Safari'] },
    { name: 'edge', patterns: ['Edge', 'Edg'] },
    { name: 'opera', patterns: ['Opera', 'Opr'] },
    { name: 'vivaldi', patterns: ['Vivaldi'] },
  ];
  let client_browser_name = 'unknown';
  for (const browser of browsers) {
    if (browser.patterns.some(pattern => userAgent.includes(pattern))) {
      client_browser_name = browser.name;
      break;
    }
  }
  mktpacket.data.client.browser_name = client_browser_name;
}

mktpacket.func.getClientBrowserLanguage()

A function that retrieves the client's browser language setting using navigator.language.

Data persists: No

Output: string (e.g., en-US, fr-FR, es-ES)

Default value: undefined

getClientBrowserLanguage: function() {
  mktpacket.data.client.browser_language = navigator.language;
}

mktpacket.func.getClientTimezone()

A function that retrieves the client's IANA time zone identifier using Intl.DateTimeFormat().resolvedOptions().timeZone.

Data persists: No

Output: string (e.g., America/New_York, Europe/Berlin, Asia/Tokyo)

Default value: undefined

getClientTimezone: function() {
  mktpacket.data.client.timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
}

mktpacket.func.getClientBatteryStatus()

A function that retrieves the client's battery status using the navigator.getBattery() API. If supported, it captures charging state, battery level, and estimated charging/discharging times. The function re-runs every second to keep the data updated.

Data persists: No

Output: object or string ("no_information" if unsupported)

Default value: undefined

getClientBatteryStatus: function() {
  if (navigator.getBattery) {
    navigator.getBattery().then(function(battery) {
      mktpacket.data.client.battery = {
        charging: battery.charging,
        level: battery.level,
        chargingTime: battery.chargingTime,
        dischargingTime: battery.dischargingTime
      };
    });
    setTimeout(window.mktpacket.func.getClientBatteryStatus, 1000);
  } else {
    mktpacket.data.client.battery = 'no_information';
  }
}

getPage functions

This functions are related to page information, like status, load time, URL parts and SEO driven data.

mktpacket.func.getPageStatus()

A function that retrieves the HTTP response status code of the current page using the Navigation Timing API. If unsupported, returns "unsupported".

Data persists: No

Output: number or string ("unsupported")

Default value: undefined

getPageStatus: function() {
  mktpacket.data.page.status = (performance.getEntriesByType('navigation')[0]?.responseStatus) ?? 'unsupported';
}

mktpacket.func.getPageLoadTime()

A function that retrieves the total load time of the current page in milliseconds using the Navigation Timing API. Returns "unsupported" if unavailable.

Data persists: No

Output: number (in ms) or string ("unsupported")

Default value: undefined

getPageLoadTime: function() {
  mktpacket.data.page.load_time = Math.floor(performance.getEntriesByType("navigation")[0].duration) ?? 'unsupported';
}

mktpacket.func.getPageUrl()

A function that captures the full URL of the current page using window.location.href.

Data persists: No

Output: string (e.g., https://example.com/path)

Default value: undefined

getPageUrl: function () {
  mktpacket.data.page.url = window.location.href;
}

mktpacket.func.getPageAnchor()

A function that captures the anchor (fragment identifier) portion of the current URL (i.e., anything after #), if present.

Data persists: No

Output: string (e.g., section1)

Default value: undefined (if no anchor is present)

getPageAnchor: function () {
  const anchor = window.location.href.split('#')[1];
  anchor && (mktpacket.data.page.anchor = anchor);
}

mktpacket.func.getPageTitle()

A function that retrieves the page's document title using document.title.

Data persists: No

Output: string (e.g., Welcome to My Site)

Default value: "no_title"

getPageTitle: function () {
  mktpacket.data.page.title = document.title ? document.title : 'no_title';
}

mktpacket.func.getPageLanguage()

A function that retrieves the language of the current page from the <html lang> attribute.

Data persists: No

Output: string (e.g., en, fr, es)

Default value: "no_language"

getPageLanguage: function () {
  mktpacket.data.page.language = document.documentElement.lang ? document.documentElement.lang : 'no_language';
}

mktpacket.func.getPageMetadata()

A function that collects all metadata from <meta> tags with name or property attributes, storing them as key-value pairs in an object.

Data persists: No

Output: object (e.g., { description: "...", og:title: "..." })

Default value: undefined (if no metadata is found)

getPageMetadata: function() {
  const metadata = {};
  const metaTags = document.getElementsByTagName('meta');
  for (const meta of metaTags) {
    const key = meta.getAttribute('name') || meta.getAttribute('property');
    const content = meta.getAttribute('content');
    if (key && content) {
      metadata[key] = content;
    }
  }
  if(Object.keys(metadata).length) {
    mktpacket.data.page.metadata = metadata;
  }
}

mktpacket.func.getPageReferrer(storageType)

A function that checks the referring URL and stores it in either localStorage or sessionStorage depending on the provided storageType ("local" or "session"). Only external referrers (different hostname) are recorded. Data is stored under a key like mktpacket_referrer_session.

Data persists: Optional (mktpacket.ctrl.persist must include the relevant key)

Output: string (e.g., https://external.com or no_referrer)

Default value: null until detected

getPageReferrer: function (storageType = 'session') {
  const storage = storageType === 'local' ? localStorage : sessionStorage;
  const keySuffix = storageType === 'local' ? 'referrer_local' : 'referrer_session';
  const storageKey = 'mktpacket_' + keySuffix;
  let referrer = storage.getItem(storageKey);
  if (referrer === null) {
    const isExternalRef = document.referrer && !document.referrer.includes(location.hostname);
    referrer = isExternalRef ? document.referrer : 'no_referrer';

    if (mktpacket.ctrl.persist.includes(keySuffix)) {
      storage.setItem(storageKey, referrer);
    }
  }
  mktpacket.data.page[keySuffix] = referrer;
}

mktpacket.func.getPageParameters()

A function that extracts all query parameters from the page URL and stores them as key-value pairs.

Data persists: No

Output: object (e.g., { utm_source: "google", campaign: "spring" })

Default value: undefined (if no parameters found)

getPageParameters: function () {
  const urlParams = new URLSearchParams(window.location.search);
  const parameters = {};

  for (const [key, value] of urlParams.entries()) {
    parameters[key] = value;
  }

  if (Object.keys(parameters).length) {
    mktpacket.data.page.parameters = parameters;
  }
}

mktpacket.func.getPageHeaviestResource()

Identifies the single largest *uncached* resource (by transfer size) loaded on the current page using the Performance API, and stores its details in mktpacket.data.page.heaviest_resource.

Data persists: No

Output: void

Stored Fields:

  • name – URL of the heaviest uncached resource, or 'resources_cached' if all were cached
  • size_bytes – Transfer size in bytes
  • load_time_ms – Load duration in milliseconds (float, 2 decimal precision)

Fallback Behavior:

  • If performance.getEntriesByType('resource') returns an empty array, name is set to null.
  • If all resources have a transferSize of 0 (i.e. fully cached), name is set to 'resources_cached'.

getPageHeaviestResource: function () {
  const resources = performance.getEntriesByType('resource');
  const uncached = resources.filter(res => res.transferSize > 0);

  if (uncached.length === 0) {
    mktpacket.data.page.heaviest_resource = {
      name: resources.length === 0 ? null : 'resources_cached',
      size_bytes: 0,
      load_time_ms: 0
    };
    return;
  }

  const heaviest = uncached.reduce((max, res) =>
    res.transferSize > max.transferSize ? res : max
  );

  mktpacket.data.page.heaviest_resource = {
    name: heaviest.name,
    size_bytes: heaviest.transferSize,
    load_time_ms: parseFloat(heaviest.duration.toFixed(2))
  };
}

mktpacket.func.getPageCoreWebVitals()

Captures Core Web Vitals metrics using the PerformanceObserver API and stores them in mktpacket.data.page.core_web_vitals. Metrics collected include:

  • LCP (Largest Contentful Paint) – Time to render the largest visible content element
  • FID (First Input Delay) – Time between user interaction and browser response
  • CLS (Cumulative Layout Shift) – Total shift score of visible elements
  • TTFB (Time to First Byte) – Server response latency
  • INP (Interaction to Next Paint) – Estimated from long interaction events (duration > 40ms)

Data persists: No

Output: void

Each metric is stored with a precision of 2 decimal places.

getPageCoreWebVitals: function () {
  if (!mktpacket.data.page.core_web_vitals) mktpacket.data.page.core_web_vitals = {};

  const toFixed2 = (num) => Number(num.toFixed(2));

  new PerformanceObserver((entryList) => {
    const entries = entryList.getEntries();
    const lastEntry = entries[entries.length - 1];
    if (lastEntry) {
      const lcp = lastEntry.renderTime || lastEntry.loadTime;
      mktpacket.data.page.core_web_vitals.lcp = toFixed2(lcp);
    }
  }).observe({ type: 'largest-contentful-paint', buffered: true });

  new PerformanceObserver((entryList) => {
    const entry = entryList.getEntries()[0];
    if (entry) {
      const fid = entry.processingStart - entry.startTime;
      mktpacket.data.page.core_web_vitals.fid = toFixed2(fid);
    }
  }).observe({ type: 'first-input', buffered: true });

  let clsValue = 0;
  new PerformanceObserver((entryList) => {
    for (const entry of entryList.getEntries()) {
      if (!entry.hadRecentInput) {
        clsValue += entry.value;
      }
    }
    mktpacket.data.page.core_web_vitals.cls = toFixed2(clsValue);
  }).observe({ type: 'layout-shift', buffered: true });

  const navEntry = performance.getEntriesByType('navigation')[0];
  if (navEntry) {
    const ttfb = navEntry.responseStart - navEntry.startTime;
    mktpacket.data.page.core_web_vitals.ttfb = toFixed2(ttfb);
  } else if (performance.timing) {
    const t = performance.timing;
    const ttfb = t.responseStart - t.requestStart;
    mktpacket.data.page.core_web_vitals.ttfb = toFixed2(ttfb);
  }

  let totalInteractionDelay = 0;
  let interactionCount = 0;
  new PerformanceObserver((list) => {
    for (const entry of list.getEntries()) {
      if (entry.duration > 40) {
        totalInteractionDelay += entry.duration;
        interactionCount++;
      }
    }
    if (interactionCount > 0) {
      const inp = totalInteractionDelay / interactionCount;
      mktpacket.data.page.core_web_vitals.inp = toFixed2(inp);
    }
  }).observe({ type: 'event', buffered: true, durationThreshold: 40 });
}

mktpacket.func.getPageColors()

Note

This function is not executed at library .init() section. It can be called later and read via mktpacket.data.page.colors

A function that collects all distinct visible colors (text, background, and borders) used throughout the page, excluding black, white, and transparent. It counts how often each color appears and converts the format from RGBA to HEX.

Data persists: No

Output: Array<object> — List of colors with RGBA, HEX, and usage count.

Default value: []

getPageColors: function () {
  let includeZeroWidth = false;
  let allColors = {};
  let props = ["background-color", "color", "border-top-color", "border-right-color", "border-bottom-color", "border-left-color"];
  let skipColors = { "rgb(0, 0, 0)": 1, "rgba(0, 0, 0, 0)": 1, "rgb(255, 255, 255)": 1 };

  [].forEach.call(document.querySelectorAll("*"), function (node) {
    var nodeColors = {};
    props.forEach(function (prop) {
      let color = window.getComputedStyle(node, null).getPropertyValue(prop);
      let isBorder = prop.includes("border");
      let notZeroWidth = isBorder ? window.getComputedStyle(node, null).getPropertyValue(prop.replace("color", "width")) !== "0px" : true;

      if (color && !skipColors[color] && (includeZeroWidth || notZeroWidth)) {
        if (!nodeColors[color]) {
          allColors[color] = (allColors[color] || { count: 0 });
          allColors[color].count++;
          nodeColors[color] = true;
        }
      } 
    });
  });

  mktpacket.data.page.colors = Object.entries(allColors).map(([rgba, { count }]) => {
    var rgb = rgba.match(/\d+/g).slice(0, 3).map(Number);
    var hex = "#" + rgb.map(c => (c < 16 ? "0" : "") + c.toString(16)).join("");
    return { rgba: rgba, hex: hex, elements_count: count };
  }).sort((a, b) => b.elements_count - a.elements_count);
}

mktpacket.func.getPageClickCount()

A function that tracks all click events on the page and logs them in a structured object keyed by a generated element descriptor. It captures click counts and the last click timestamp (in seconds) for each unique element.

Data persists: No

Output: object (e.g., { "button#submit": { count: 3, last_click_timestamp: 1715700000 } })

Default value: {}

getPageClickCount: function () {
  if (!mktpacket.data.page.click_count) {
    mktpacket.data.page.click_count = {};
  }

  document.addEventListener('click', function (event) {
    const el = event.target;
    let descriptor = el.tagName.toLowerCase();
    if (el.id) {
      descriptor += `#${el.id}`;
    } else if (el.className && typeof el.className === 'string') {
      descriptor += '.' + el.className.trim().split(/\s+/).join('.');
    }
    if (descriptor === 'div' || descriptor === 'span' || descriptor === 'p' || descriptor === 'a') {
      descriptor += '[inner="' + el.innerText.trim().slice(0, 15) + '"]';
    }

    if (!mktpacket.data.page.click_count[descriptor]) {
      mktpacket.data.page.click_count[descriptor] = {
        count: 0,
        last_click_timestamp: null
      };
    }

    const clickData = mktpacket.data.page.click_count[descriptor];
    clickData.count++;
    clickData.last_click_timestamp = Math.floor(Date.now() / 1000);
  });
}

getUser functions

This functions are related to user information, like it has adBlock enabled, it's a potential bot, already visited a page, or how much time has spent on page.

mktpacket.func.getUserLocalDatetime()

A function that captures the user's local date and time information, including ISO format, locale string, timezone offset, and timestamp.

Data persists: No

Output: object with the following properties:

  • iso: string – ISO 8601 format (e.g., 2025-05-23T14:35:00.000Z)
  • locale_string: string – User’s locale-formatted date and time
  • timezone_offset_minutes: number – Timezone offset from UTC in minutes
  • timestamp: number – Seconds since the Unix epoch

Default value: undefined (object created only when function is called)

getUserLocalDatetime: function () {
  const now = new Date();

  if (!mktpacket.data.user) mktpacket.data.user = {};
  mktpacket.data.user.local_datetime = {
    iso: now.toISOString(),
    locale_string: now.toLocaleString(),
    timezone_offset_minutes: now.getTimezoneOffset() * -1,
    timestamp: now.getTime()
  };
}

mktpacket.func.getUserIsBot()

A function that detects whether the client appears to be a bot based on several navigator properties and the user agent string. It checks for missing navigator fields, automation indicators (like navigator.webdriver), and known bot keywords in the user agent.

Data persists: No

Output: boolean

Default value: false

getUserIsBot: function() {
  const is_bot_navigator = !navigator.language || 
                         !navigator.languages || 
                         navigator.languages.length === 0 || 
                         navigator.webdriver || 
                         navigator.doNotTrack !== null || 
                         navigator.hardwareConcurrency === undefined || 
                         navigator.maxTouchPoints === undefined;

  const userAgent = navigator.userAgent.toLowerCase();
  const is_bot_useragent = /bot|crawler|spider|robot|crawling/i.test(userAgent);

  mktpacket.data.user.is_bot = is_bot_navigator || is_bot_useragent;
}

mktpacket.func.getUserFirstPage(storageType)

A function that captures and stores the first page visited by the user during the session or across sessions, based on the specified storage type ('session' or 'local').

Data persists: Yes

Output: string – The URL of the user's first visited page

Default value: undefined (until set on first function call)

getUserFirstPage: function (storageType = 'session') {
  const storage = storageType === 'local' ? localStorage : sessionStorage;
  const keySuffix = storageType === 'local' ? 'first_page_local' : 'first_page_session';
  const storageKey = 'mktpacket_' + keySuffix;

  let firstPage = storage.getItem(storageKey);

  if (firstPage === null) {
    firstPage = document.URL;
    if (mktpacket.ctrl.persist.includes(keySuffix)) {
      storage.setItem(storageKey, firstPage);
    }
  }

  mktpacket.data.user[keySuffix] = firstPage;
}

mktpacket.func.getUserTimeOnPage()

A function that tracks how long the user has spent on the current page. The timer starts when the function is called and updates every second.

Data persists: No (resets on page reload)

Output: number – Time on page in seconds

Default value: 0 (starts from zero on each page load)

getUserTimeOnPage: function () {
  const startTime = Date.now();
  const updateTime = () => {
    const now = Date.now();
    const timeOnPage = Math.floor((now - startTime) / 1000);
    mktpacket.data.user.time_on_page = timeOnPage;
  };
  const interval = setInterval(updateTime, 1000);
  window.addEventListener('beforeunload', () => {
    updateTime();
    clearInterval(interval);
  });
}

mktpacket.func.getUserTimeOnWebsite()

A function that tracks the total time a user has spent on the website during the current session. It accumulates time across page views and stores it in sessionStorage.

Data persists: Yes (within the same session)

Output: number – Total time on website in seconds

Default value: 0 (accumulates per session)

getUserTimeOnWebsite: function () {
  const key = 'mktpacket_' + 'time_on_website';
  const savedTime = parseInt(sessionStorage.getItem(key), 10);
  let totalTime = isNaN(savedTime) ? 0 : savedTime;
  const startTime = Date.now();

  const updateTime = () => {
    const now = Date.now();
    const sessionTime = Math.floor((now - startTime) / 1000);
    const currentTotal = totalTime + sessionTime;
    mktpacket.data.user.time_on_website = currentTotal;
    sessionStorage.setItem(key, currentTotal);
  };

  const interval = setInterval(updateTime, 1000);

  window.addEventListener('beforeunload', () => {
    updateTime();
    clearInterval(interval);
  });
}

mktpacket.func.getUserIsReturning()

A function that detects if the user has visited the website before using localStorage. Sets a flag on the first visit for future reference.

Data persists: Yes (across sessions, using localStorage)

Output: booleantrue if user is returning, false otherwise

Default value: false (until first visit is recorded)

getUserIsReturning: function () {
  const hasVisited = localStorage.getItem('mktpacket_' + 'user_returning') === 'true';
  mktpacket.data.user.is_returning = hasVisited;
  if (!hasVisited) {
    localStorage.setItem('mktpacket_' + 'user_returning', 'true');
  }
}

mktpacket.func.getUserHashedIP()

PRO Feature

This feature will be available on free version tier until 6th January 2026

Fetches the user's hashed IP address using the backend API and stores it in mktpacket.data.user.hashed_ip.

Data persists: No

Output: void

Notes:

  • Uses auxAPIConnect() with the function name 'getUserHashedIP'
  • Relies on the mktpacket.ctrl.api_response for value
getUserHashedIP: function() {
  mktpacket.func.auxAPIConnect(function () {
    mktpacket.data.user.hashed_ip = mktpacket.ctrl.api_response;
  }, 'getUserHashedIP');
}

mktpacket.func.getUserISP()

PRO Feature

This feature will be available on free version tier until 6th January 2026

Retrieves the user's Internet Service Provider (ISP) from the backend and stores it in mktpacket.data.user.isp.

Data persists: No

Output: void

Notes:

  • Uses auxAPIConnect() with the function name 'getUserISP'
  • Result is sourced from mktpacket.ctrl.api_response
getUserISP: function() {
  mktpacket.func.auxAPIConnect(function () {
    mktpacket.data.user.isp = mktpacket.ctrl.api_response;
  }, 'getUserISP');
}

mktpacket.func.getUserUniqueID()

PRO Feature

This feature will be available on free version tier until 6th January 2026

Obtains a unique identifier (UUID) for the user from the backend API and assigns it to mktpacket.data.user.uuid.

Data persists: Yes (stored in localStorage if uuid is listed in mktpacket.ctrl.persist)

Output: void

Notes:

  • Uses auxAPIConnect() with the function name 'getUserUniqueID'
  • If persistence is enabled, stores the UUID in localStorage with key mktpacket_uuid
getUserUniqueID: function () {
  mktpacket.func.auxAPIConnect(function () {
    mktpacket.data.user.uuid = mktpacket.ctrl.api_response;
    if (mktpacket.ctrl.persist.includes('uuid')) {
      localStorage.setItem('mktpacket_' + 'uuid', mktpacket.data.user.uuid);
    }
  }, 'getUserUniqueID', true);
}

Integrations

The library counts on numerous integrations and helpers from 3rd party codes.

This object sections are present only if the corresponding code was found on page.

Marketing related functions

mktpacket.func.getAdClick()

A function that detects known advertising click identifiers in the URL parameters and records the ad click source and value.

Data persists: No

Output: object – Contains the detected ad parameter and its value:

  • click_source: string – Name of the detected ad parameter (e.g., gclid)
  • click_value: string – Value of the ad parameter

Default value: undefined (set only if a known ad parameter is found)

getAdClick: function () {
  const adList = ['click_id', 'li_click_id', 'pinid', 'rid', 'tid', 'scid',
                  'msclkid', 'dclid', 'twclid', 'ttclid', 'fbclid', 'gclid'];
  for (let key in mktpacket.data.page.parameters) {
    if (adList.includes(key.toLowerCase())) {
      mktpacket.data.ad = {};
      mktpacket.data.ad.click_source = key;
      mktpacket.data.ad.click_value = mktpacket.data.page.parameters[key];
    }
  }
}

GA related functions

mktpacket.func.getGAClientId()

A function that retrieves the Google Analytics Client ID using the gtag API. This ID is used to uniquely identify a user in GA.

Data persists: No

Output: string – GA Client ID (if available)

Default value: undefined (set asynchronously if available)

getGAClientId: function () {
  if (typeof gtag === 'function' && (mktpacket.ctrl.gtag_id !== null || mktpacket.ctrl.gtag_id !== '')) {
    gtag('get', mktpacket.conf.gtag_id, 'client_id', function (clientId) { 
      if (clientId) {
        mktpacket.data.ga = mktpacket.data.ga || {};
        mktpacket.data.ga.client_id = clientId;
      }
    })
  }
}

mktpacket.func.getGASessionId()

A function that retrieves the current Google Analytics Session ID using the gtag API. This helps track user sessions more precisely.

Data persists: No

Output: string – GA Session ID (if available)

Default value: undefined (set asynchronously if available)

getGASessionId: function () {
  if (typeof gtag === 'function' && (mktpacket.ctrl.gtag_id !== null || mktpacket.ctrl.gtag_id !== '')) {
    gtag('get', mktpacket.conf.gtag_id, 'session_id', function (sessionId) {
      if (sessionId) {
        mktpacket.data.ga = mktpacket.data.ga || {};
        mktpacket.data.ga.session_id = sessionId;
      }
    })
  }
}

ABTasty related functions

mktpacket.func.getABTasty()

A function that extracts active A/B test data from the ABTasty global object (if available). Captures campaign and variation information for analysis.

Data persists: No

Output: object – Details of the A/B test on the current page:

  • campaign_id: number – Campaign ID
  • campaign_name: string – Campaign name
  • variation_id: number – Variation ID
  • variation_name: string – Variation name
  • type: string – Type of test
  • sub_type: string – Sub-type of test
  • status: string – Test status
  • trigger_mode: string – Trigger mode

Default value: undefined (only set if tests are detected)

getABTasty: function () {
  if (typeof ABTasty !== 'undefined' && typeof ABTasty.getTestsOnPage === 'function') {
    var tests = ABTasty.getTestsOnPage();
    if (tests && Object.keys(tests).length > 0) {
      for (let testId in tests) {
        if (tests.hasOwnProperty(testId)) {
          let test = tests[testId];
          mktpacket.data.abtasty = {};
          mktpacket.data.abtasty.campaign_id = Number(testId);
          mktpacket.data.abtasty.campaign_name = test.name;
          mktpacket.data.abtasty.variation_id = test.variationID;
          mktpacket.data.abtasty.variation_name = test.variationName;
          mktpacket.data.abtasty.type = test.type;
          mktpacket.data.abtasty.sub_type = test.sub_type;
          mktpacket.data.abtasty.status = test.status;
          mktpacket.data.abtasty.trigger_mode = test.triggerMode;
        }
      }
    }
  }
}

OneTrust related functions

mktpacket.func.getOneTrust()

A function that captures user consent data from the OneTrust CMP (Consent Management Platform). It records Google consent status and active consent groups if available.

Data persists: No

Output: object – Contains consent-related data:

  • google_consent: boolean – Whether Google consent is granted
  • active_groups: string – Active consent group IDs (read dynamically)

Default value: undefined (set only if OneTrust is available)

getOneTrust: function () {
  if (typeof OneTrust !== 'undefined') {
    function getActiveGroups() {
      return OnetrustActiveGroups;
    }
    mktpacket.data.onetrust = {
      google_consent: OneTrust.GetDomainData().GoogleConsent,
      get active_groups() {
        return getActiveGroups();
      }
    };
  }
}

Utilities

This section is dedicated to all utilities, auxiliar functions that are not called on request to update object data, but rather observers.

Auxiliar functions

mktpacket.func.auxTrackFormSubmissions()

A utility function that listens for form submissions across the site and stores related data in localStorage. This allows detection of whether a user has previously submitted a form, along with basic metadata about the submission.

Data persists: Yes (via localStorage key mktpacket_form_data)

Output: object – Form metadata:

  • prev_submitted: boolean – Whether a form has been submitted previously
  • id: string|null – The ID of the submitted form (if available)
  • url: string – Page URL where submission occurred
  • timestamp: number – UNIX timestamp of the submission event

Default value: { prev_submitted: false }

auxTrackFormSubmissions: function () {
  mktpacket.data.page.form = {};
  const stored = localStorage.getItem('mktpacket_form_data');
  if (stored) {
    try {
      mktpacket.data.page.form = JSON.parse(stored);
    } catch {
      mktpacket.data.page.form = { prev_submitted: false };
    }
  } else {
    mktpacket.data.page.form.prev_submitted = false;
  }

  function storeFormSubmission(form) {
    mktpacket.data.page.form.prev_submitted = true;
    mktpacket.data.page.form.id = form.id || null;
    mktpacket.data.page.form.url = window.location.href || null;
    mktpacket.data.page.form.timestamp = Math.floor(Date.now() / 1000);
    localStorage.setItem('mktpacket_form_data', JSON.stringify(mktpacket.data.page.form));
  }

  document.addEventListener('submit', function(event) {
    const form = event.target;
    if (form.tagName.toLowerCase() === 'form') {
      storeFormSubmission(form);
    }
  }, true);

  document.addEventListener('click', function(event) {
    const btn = event.target.closest('button[type="submit"], input[type="submit"]');
    if (!btn) return;
    const form = btn.closest('form');
    if (form) {
      setTimeout(() => {
        storeFormSubmission(form);
      }, 100);
    }
  }, true);

  if (window.fetch) {
    const origFetch = window.fetch;
    window.fetch = function(...args) {
      const [resource, config] = args;
      if (config && config.method && config.method.toUpperCase() === 'POST') {
        const forms = document.querySelectorAll('form');
        const visibleForm = Array.from(forms).find(f => f.offsetParent !== null);
        if (visibleForm) {
          storeFormSubmission(visibleForm);
        }
      }
      return origFetch.apply(this, args);
    };
  }
}

mktpacket.func.auxGTagObserver(callback)

A utility function that waits for the gtag function to become available. If gtag is already defined, the callback is executed immediately. Otherwise, a MutationObserver monitors the DOM for changes that indicate gtag has loaded, triggering the callback once available.

Data persists: No

Output: void – Executes the provided callback once gtag is detected

Default value: undefined

Parameters:

  • callback (function) – The function to execute once gtag is ready

Behavior:

  • If gtag is immediately available, callback is called instantly
  • Otherwise, DOM changes are observed for up to 5 seconds
  • Callback is called once gtag becomes available
auxGTagObserver: function (callback) {
  if (typeof gtag === 'function') {
    callback();
    return;
  }
  const gtagobserver = new MutationObserver(() => {
    if (typeof gtag === 'function') {
      gtagobserver.disconnect();
      callback();
    }
  });
  gtagobserver.observe(document.documentElement, {
    childList: true,
    subtree: true,
  });
  setTimeout(() => {
    gtagobserver.disconnect();
  }, 5000);
}

mktpacket.func.auxPageURLObserver(callback)

A utility function that listens for changes to the page URL via the History API (popstate) and hash changes (hashchange). The callback is invoked immediately with the current URL, and again whenever the URL changes.

Data persists: No

Output: function – A function that can be called to remove the event listeners

Default value: undefined

Parameters:

  • callback (function) – Function to execute on initial load and every URL change, receives window.location.href as its argument

Usage notes:

  • Supports SPA navigation events without reloading the page
  • Returns a cleanup function to unbind the event listeners
auxPageURLObserver: function (callback) {
  callback(window.location.href);
  const checkUrlChange = () => {
    callback(window.location.href);
  };
  window.addEventListener('popstate', checkUrlChange);
  window.addEventListener('hashchange', checkUrlChange);

  return () => {
    window.removeEventListener('popstate', checkUrlChange);
    window.removeEventListener('hashchange', checkUrlChange);
  };
}

mktpacket.func.auxAPIConnect(callback, func_name = 'getAllData')

Connects to the mktpacket backend API using a stored API key, fetches data, and merges it into the mktpacket object. Supports optional callback execution after successful response.

Data persists: Conditional (based on mktpacket.ctrl.persist)

Output: void

Default value: undefined

Parameters:

  • callback (function, optional) – Function to run after data is merged
  • func_name (string) – API function name to call (default: 'getAllData')

Notes:

  • Uses XMLHttpRequest to communicate with: https://codebakers.dev/apis/mktpacket/
  • Response data is merged using auxObjectMerge
  • Requires mktpacket.ctrl.api_key to be set
auxAPIConnect: function (callback, func_name = 'getAllData') {
  const api_key = mktpacket.ctrl.api_key;
  if (!api_key) return;
  const apiUrl = 'https://codebakers.dev/apis/mktpacket/';
  const xhr = new XMLHttpRequest();
  xhr.onload = function () {
    if (xhr.status === 200) {
      const jsonResponse = xhr.response;
      if (jsonResponse) {
        const usePersistedValues = (func_name === 'getAllData');
        mktpacket.func.auxObjectMerge(mktpacket, jsonResponse, usePersistedValues);
        if (callback) callback();
      }
    } else {
      console.error('API call failed: ', xhr.status);
    }
  };
  xhr.open('POST', apiUrl, true);
  xhr.responseType = 'json';
  xhr.setRequestHeader('Content-Type', 'application/json');
  xhr.send(JSON.stringify({ key: api_key, func: func_name }));
}

mktpacket.func.auxObjectMerge(target, source, usePersistedValues = true)

Recursively merges properties from a source object into a target object. For keys listed in mktpacket.ctrl.persist, values are stored in and optionally retrieved from localStorage.

Data persists: Yes (conditionally based on persist config)

Output: object – The merged target object

Parameters:

  • target (object) – The destination object for the merge
  • source (object) – The source object to merge into target
  • usePersistedValues (boolean, optional) – If true, uses values from localStorage when available (default: true)

Notes:

  • Used internally by auxAPIConnect
  • Safely handles nested objects
auxObjectMerge: function (target, source, usePersistedValues = true) {
  for (const key of Object.keys(source)) {
    const valueFromSource = source[key];
    if (valueFromSource instanceof Object && key in target && typeof target[key] === 'object') {
      mktpacket.func.auxObjectMerge(target[key], valueFromSource, usePersistedValues);
    } else {
      const shouldPersist = mktpacket.ctrl.persist.includes(key);
      if (shouldPersist) {
        const persistedValue = localStorage.getItem('mktpacket_' + key);
        if (usePersistedValues && persistedValue !== null) {
          target[key] = persistedValue;
        } else {
          target[key] = valueFromSource;
          localStorage.setItem('mktpacket_' + key, valueFromSource);
        }
      } else {
        target[key] = valueFromSource;
      }
    }
  }
  return target;
}

mktpacket.func.auxReadyEvent()

Dispatches a custom dataLayer event called mktpacket_ready, indicating that mktpacket has completed initialization. Also includes the license key from mktpacket.ctrl.license.

Data persists: No

Output: void

Default value: undefined

Behavior:

  • Pushes a structured object to window.dataLayer
  • Primarily used for analytics triggers (e.g., GTM)
auxReadyEvent: function () {
  window.dataLayer.push({
    'event': 'mktpacket_ready',
    'license': mktpacket.ctrl.license,
  });
}

Example Usage

Soon™

FAQs

Below you'll find answers to common questions about using the mktpacket library for web data collection and analytics.

Data storage (by mktpacket Library)

What data, either my company or my clients is processed by this library

No data is stored or detained within mktpacket API endpoint. All of the JS data is managed locally inside users browser, and sections like IP, ISP or UUID are not stored within any database inside our tech stack. All data usage is responsibility of the company that loads the library.

We will only storage a web domain -> api-key association to ensure PRO features load correctly, and a counter on how many requests have been launched within that domain for our infrastructure scalability planning.

Where does the data come from?

All of the data listed is fetch from either browser internal information (that is easily accesible from the corresponding application APIs) or connection details of the user (like a hashed IP or ISP).

To ensure transparency we list all of the individual funcions within the Docs, and we don't obfuscate our code, also keeping the funcions as simple and readable as possible.

No privilege abuses or tricky sources about user information is pursued. Be aware that if the data is present within this library, any big corp. already has this information about it's clients.

Will this library reduce my website performance?

Our principal focus while developing and delivering new features to the library, is to prevent any kind of heavy load and performance issues, the library implements systems that loads the code in a way that the blockages are minimal.

Implementation

Soon™

Usage

Soon™

Misc.

Soon™