npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@anishwij/meta-cookies

v0.1.2

Published

Lightweight server-side Meta (Facebook) Pixel cookie management for Next.js middleware

Readme

@anishwij/meta-cookies

A lightweight, server-side implementation for handling Meta (Facebook) Pixel cookies (_fbc and _fbp) in Next.js applications. Fully aligned with Meta's official CAPI Param Builder implementation, ensuring maximum compatibility with the Conversions API and Pixel events.

Features

Core Functionality

  • 5-Segment Cookie Format: Implements Meta's official format with language/version token appendix
  • Automatic Cookie Management: Sets/updates _fbc when fbclid is detected in URL or referrer
  • Smart FBP Generation: Creates _fbp cookies with unique identifiers following Meta's spec
  • Legacy Cookie Migration: Automatically upgrades 4-segment cookies to new 5-segment format

Advanced Features

  • Enhanced Domain Resolution:
    • IP address support (IPv4/IPv6 with bracketing)
    • Multi-part TLD handling (e.g., .co.uk, .com.au)
    • Custom ETLD+1 resolver interface
  • Browser Compatibility: Chrome detection for optimal SameSite attribute handling
  • Smart Update Logic: Only updates timestamps when payloads change (not on every request)
  • Version Tracking: Encodes package version in cookie appendix for debugging
  • TypeScript-First: Full type safety with comprehensive interfaces

Installation

npm install @anishwij/meta-cookies
yarn add @anishwij/meta-cookies
pnpm add @anishwij/meta-cookies
bun add @anishwij/meta-cookies

Requires Next.js >= 13 (for middleware support).

Usage

Basic Integration in Next.js Middleware

Import and use in your middleware.ts file:

import { NextRequest, NextResponse } from 'next/server';
import { addMetaCookies } from '@anishwij/meta-cookies';

export function middleware(request: NextRequest) {
  const response = NextResponse.next();
  return addMetaCookies(request, response);
}

export const config = {
  matcher: ['/((?!_next/static|_next/image|favicon.ico).*)'],
};

This will automatically handle Meta cookies on all routes (excluding static assets).

With Configuration

Pass options to customize behavior:

import { addMetaCookies } from '@anishwij/meta-cookies';

export function middleware(request: NextRequest) {
  const response = NextResponse.next();
  return addMetaCookies(request, response, {
    constants: { MAX_AGE: 3600 * 24 * 90 }, // 90 days in seconds
    isSecure: true, // Force secure flag
    etldPlus1Resolver: ['example.com', 'subdomain.example.com'], // Custom domain list
    packageVersion: '0.1.0', // Optional: override version for appendix
  });
}

Standalone Helpers

For custom logic (e.g., in API routes or server components):

import { NextRequest } from 'next/server';
import { extractFbclid, formatFbc, getRootDomainFromHost } from '@anishwij/meta-cookies';

export async function GET(request: NextRequest) {
  const fbclid = extractFbclid(request);
  if (fbclid) {
    const domain = getRootDomainFromHost(request.headers.get('host') || '');
    const subdomainIndex = domain.split('.').length - 1;
    const fbc = formatFbc(fbclid, subdomainIndex);
    // Use in your response or Conversions API payload
  }
  // ...
}

Extracting Cookies Server-Side

import { getMetaCookies } from '@anishwij/meta-cookies';

const { fbc, fbp } = getMetaCookies(request);
// Send to Meta Conversions API

Preparing Event Params

import { prepareMetaEventParams } from '@anishwij/meta-cookies';

const params = prepareMetaEventParams(request);
// Use in fetch to Meta API: { ...eventData, ...params }

Deleting Cookies

import { deleteMetaCookies } from '@anishwij/meta-cookies';

deleteMetaCookies(response);
// e.g., in a logout route

Refreshing Cookies

import { refreshMetaCookies } from '@anishwij/meta-cookies';

refreshMetaCookies(request, response);
// Regenerates if invalid or missing

API Reference

Note: All modules are re-exported from the package root (e.g., import { ParsedCookie } from '@anishwij/meta-cookies').

addMetaCookies(request: NextRequest, response: NextResponse, options?: MetaCookiesOptions): NextResponse

The main function to add/update Meta cookies. Mutates and returns the response.

  • Parameters:
    • request: The incoming Next.js request.
    • response: The Next.js response object (e.g., from NextResponse.next()).
    • options (optional): Customization options (see below).

MetaCookiesOptions

interface MetaCookiesOptions {
  constants?: Partial<MetaCookieConstants>; // Override defaults like cookie names or max age
  isSecure?: boolean; // Override protocol-based secure flag
  etldPlus1Resolver?: ETLDPlus1Resolver | string[]; // Advanced domain resolution
  packageVersion?: string; // Version for appendix encoding
}

MetaCookieConstants (Defaults)

const META_COOKIE_DEFAULTS = {
  FBC_NAME: '_fbc',
  FBP_NAME: '_fbp',
  MAX_AGE: 7776000, // 90 days in seconds
  PREFIX: 'fb',
  FBCLID_MAX_LENGTH: 500, // Max length for fbclid param
} as const;

const COOKIE_FORMAT = {
  MIN_SEGMENTS: 4, // Legacy format
  MAX_SEGMENTS: 5, // New format with appendix
  DEFAULT_FORMAT: 0x01,
  LANGUAGE_TOKEN_INDEX: 0x04, // Node.js
  APPENDIX_LENGTH_V1: 2, // Legacy 2-char tokens
  APPENDIX_LENGTH_V2: 8, // New 8-char appendix
} as const;

Exported Helpers

Cookie Management

  • parseCookie(value: string, prefix?: string): ParsedCookie - Validates and parses a cookie value (supports 4-5 segments, configurable prefix).
  • extractFbclid(request: NextRequest, maxLength?: number): string | null - Gets fbclid from URL or referrer.
  • formatFbc(fbclid: string, subdomainIndex: number, prefix?: string, version?: string): string - Formats _fbc value with appendix.
  • formatFbp(subdomainIndex: number, prefix?: string, version?: string): string - Formats _fbp value with appendix.
  • updateCookieWithLanguageToken(cookieValue: string, version?: string): string - Adds appendix to 4-segment cookies.
  • preprocessCookie(value: string | null | undefined, subdomainIndex: number, version?: string, prefix?: string): CookieData | null - Processes and validates existing cookies.
  • getMetaCookies(request: NextRequest, constants?: MetaCookieConstants): { fbc: string | null; fbp: string | null } - Extracts and validates Meta cookies.
  • prepareMetaEventParams(request: NextRequest, constants?: MetaCookieConstants): { fbc?: string; fbp?: string } - Prepares params for Meta API events.
  • deleteMetaCookies(response: NextResponse, constants?: MetaCookieConstants): NextResponse - Deletes Meta cookies.
  • refreshMetaCookies(request: NextRequest, response: NextResponse, options?: MetaCookiesOptions): NextResponse - Refreshes/repairs invalid or missing cookies.

Domain Resolution

  • getRootDomainFromHost(host: string): string - Enhanced root domain extraction with IP and multi-TLD support.
  • getRootDomainFromHostEnhanced(host: string): string - Advanced version with extended TLD list.
  • getSubdomainIndex(domain: string): number - Calculates the subdomain index.
  • computeETLDPlus1ForHost(host: string, resolver?: ETLDPlus1Resolver | string[]): { etldPlus1: string; subdomainIndex: number } - Advanced ETLD+1 computation.
  • DomainListResolver - Class implementing ETLDPlus1Resolver interface for custom domain lists.
  • getSimpleETLDPlus1(hostname: string): string - Basic ETLD+1 calculation.

Utilities

  • isIPAddress(value: string): boolean - Detects IPv4 or IPv6 addresses.
  • isIPv4Address(value: string): boolean - Validates IPv4 format.
  • isIPv6Address(value: string): boolean - Validates IPv6 format.
  • maybeBracketIPv6(value: string): string - Adds brackets to IPv6 addresses for cookies.
  • extractHostFromHttpHost(value: string): string | null - Extracts hostname from HTTP host header.
  • isDigit(str: string): boolean - Checks if string is all digits.
  • getAppendixInfo(isNew: boolean, version?: string): string - Generates version appendix for cookies.

Browser Detection

  • detectBrowser(userAgent?: string | null): BrowserInfo - Analyzes user agent for browser detection.
  • getSameSiteAttribute(userAgent?: string | null): 'lax' | 'none' | undefined - Determines appropriate SameSite attribute.

Types

interface ParsedCookie {
  valid: boolean
  parts: string[]
  fbclid?: string
  subdomainIndex?: number
  timestamp?: number
  languageToken?: string
  prefix?: string  // Cookie prefix (e.g., 'fb')
}

interface CookieData {
  creationTime: number
  payload: string
  subdomainIndex: number
  languageToken?: string
}

interface BrowserInfo {
  isChrome: boolean
  isEdge: boolean
  isOpera: boolean
  isCriOS: boolean
  shouldUseSameSiteLax: boolean
}

interface ETLDPlus1Resolver {
  resolveETLDPlus1(hostname: string): string
}

See src/types.ts for complete type definitions.

Cookie Format

Meta cookies follow a specific format:

fb.{subdomain_index}.{timestamp}.{payload}.{appendix}
  • fb: Fixed prefix
  • subdomain_index: Number based on domain depth (e.g., 1 for .example.com)
  • timestamp: Unix timestamp in milliseconds
  • payload: The fbclid value for _fbc, random ID for _fbp
  • appendix: 8-character base64url string encoding version and metadata

Example cookies:

_fbc=fb.1.1704067200000.IwAR1a2b3c.AQQBAAEA
_fbp=fb.1.1704067200000.1234567890.AQQAAAEA

Examples

Custom Domain Logic

For advanced TLD handling (e.g., integrating a public suffix library):

import { addMetaCookies } from '@anishwij/meta-cookies';
import psl from 'psl'; // Optional external lib

const customResolver: ETLDPlus1Resolver = {
  resolveETLDPlus1: (hostname: string) => {
    const parsed = psl.parse(hostname);
    return parsed.domain || hostname;
  }
};

addMetaCookies(request, response, { etldPlus1Resolver: customResolver });

Using Domain List Resolver

For known domains without external dependencies:

import { addMetaCookies } from '@anishwij/meta-cookies';

const knownDomains = ['example.com', 'app.example.com', 'staging.example.com'];

export function middleware(request: NextRequest) {
  const response = NextResponse.next();
  return addMetaCookies(request, response, {
    etldPlus1Resolver: knownDomains // Uses built-in DomainListResolver
  });
}

IP Address Support

The package automatically handles IP addresses:

// IPv4: Sets cookies on the IP directly
// Host: 192.168.1.1 → Cookie domain: 192.168.1.1

// IPv6: Properly brackets for cookie domain
// Host: ::1 → Cookie domain: [::1]

Custom Cookie Prefix

For specialized use cases, you can use a custom prefix instead of 'fb':

import { parseCookie, formatFbc } from '@anishwij/meta-cookies';

// Parse cookie with custom prefix
const parsed = parseCookie('custom.1.1704067200000.abc123.AQQBAAEA', 'custom');

// Format cookies with custom prefix
const fbc = formatFbc('abc123', 1, 'custom');

// Use with middleware
addMetaCookies(request, response, {
  constants: { PREFIX: 'custom' }
});

Testing in Development

Run your Next.js app locally. Check cookies in browser dev tools after visiting a page with ?fbclid=example in the URL. The cookies will now include the appendix segment.

Gotchas & Best Practices

  • Cookie Format: The package now uses Meta's official 5-segment format with appendix. Legacy cookies are auto-migrated.
  • Production vs. Dev: Secure flag is auto-detected via protocol (https:). Override with isSecure if needed.
  • Domain Sharing: Cookies are set on the root domain (e.g., .example.com) for subdomain access. Test on custom domains.
  • IP Address Handling: IPv6 addresses are automatically bracketed. IPv4 addresses work as-is.
  • Browser Compatibility: Chrome gets SameSite=Lax, other browsers get no SameSite attribute for maximum compatibility.
  • Update Logic: Timestamps only update when payloads change, reducing unnecessary cookie writes.
  • Meta Compatibility: Fully aligned with Meta's CAPI Param Builder for perfect Conversions API integration.
  • Ad Blockers: Server-side setting helps bypass blockers, but client-side Pixel may still be needed for full functionality.
  • Privacy: Ensure compliance with GDPR/CCPA; these cookies track user behavior.

Acknowledgments

This package is a TypeScript implementation fully aligned with Meta's official CAPI Param Builder, implementing the exact cookie format and validation logic from Meta's reference implementation. It follows the specifications in Meta's Conversions API documentation including the 5-segment format with appendix tokens.

This is an independent implementation designed specifically for Next.js middleware, providing a clean, type-safe API while maintaining complete compatibility with Meta's standards. Not affiliated with or endorsed by Meta Platforms, Inc.

License

MIT License. See LICENSE for details.