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

@hcl-cdp-ta/hclcdp-web-sdk-react

v1.3.5

Published

HCL CDP Web SDK React Wrapper

Readme

Version

HCL CDP Web SDK for React

React wrapper and hooks for the HCL Customer Data Platform (CDP) Web SDK, providing seamless integration with React applications including Next.js.

Features

  • React Hooks: Simple useCdp() hook for accessing CDP functionality
  • Session Lifecycle Hooks: useSessionEnd() hook for handling session events
  • Context Provider: CdpProvider for application-wide CDP integration
  • Auto Page Tracking: CdpPageEvent component for declarative page tracking
  • Runtime Configuration: Dynamic settings without reinitialization
  • TypeScript Support: Full TypeScript definitions included
  • Next.js Ready: Built for modern React frameworks

Installation

npm install @hcl-cdp-ta/hclcdp-web-sdk-react
yarn add @hcl-cdp-ta/hclcdp-web-sdk-react

Quick Start

1. Wrap Your App with CdpProvider

Next.js App Router (app/layout.tsx)

import { CdpProvider, HclCdpConfig } from "@hcl-cdp-ta/hclcdp-web-sdk-react"
import { GoogleAnalytics, Facebook } from "@hcl-cdp-ta/hclcdp-web-sdk"

const config: HclCdpConfig = {
  writeKey: "your-write-key",
  cdpEndpoint: "https://your-cdp-endpoint.com",
  inactivityTimeout: 30, // Session timeout in minutes
  enableDeviceSessionLogging: true, // Track device session start/end events
  enableUserSessionLogging: true, // Track user session start/end events
  enableUserLogoutLogging: true, // Track user logout events
  destinations: [
    {
      id: "GA4",
      classRef: GoogleAnalytics,
      config: { measurementId: "G-XXXXXXXXXX" },
    },
    {
      id: "Facebook",
      classRef: Facebook,
      config: { pixelId: "your-pixel-id" },
    },
  ],
}

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en">
      <body>
        <CdpProvider config={config}>{children}</CdpProvider>
      </body>
    </html>
  )
}

Next.js Page Router (pages/_app.tsx)

// pages/_app.tsx
import { CdpProvider, HclCdpConfig } from "@hcl-cdp-ta/hclcdp-web-sdk-react"
import { GoogleAnalytics, Facebook } from "@hcl-cdp-ta/hclcdp-web-sdk"

const config: HclCdpConfig = {
  writeKey: "your-write-key",
  cdpEndpoint: "https://your-cdp-endpoint.com",
  inactivityTimeout: 30,
  enableDeviceSessionLogging: true,
  enableUserSessionLogging: true,
  enableUserLogoutLogging: true,
  destinations: [
    { id: "GA4", classRef: GoogleAnalytics, config: { measurementId: "G-XXXXXXXXXX" } },
    { id: "Facebook", classRef: Facebook, config: { pixelId: "your-pixel-id" } },
  ],
}

export default function MyApp({ Component, pageProps }) {
  return (
    <CdpProvider config={config}>
      <Component {...pageProps} />
    </CdpProvider>
  )
}

Note: CdpProvider automatically handles SSR by detecting when it's running on the server and only initializing on the client side.

Vanilla React (e.g. Create React App, Vite, etc.)

// src/index.tsx or src/main.tsx
import React from "react"
import ReactDOM from "react-dom/client"
import App from "./App"
import { CdpProvider, HclCdpConfig } from "@hcl-cdp-ta/hclcdp-web-sdk-react"
import { GoogleAnalytics, Facebook } from "@hcl-cdp-ta/hclcdp-web-sdk"

const config: HclCdpConfig = {
  writeKey: "your-write-key",
  cdpEndpoint: "https://your-cdp-endpoint.com",
  inactivityTimeout: 30,
  enableDeviceSessionLogging: true,
  enableUserSessionLogging: true,
  enableUserLogoutLogging: true,
  destinations: [
    { id: "GA4", classRef: GoogleAnalytics, config: { measurementId: "G-XXXXXXXXXX" } },
    { id: "Facebook", classRef: Facebook, config: { pixelId: "your-pixel-id" } },
  ],
}

const root = ReactDOM.createRoot(document.getElementById("root"))
root.render(
  <React.StrictMode>
    <CdpProvider config={config}>
      <App />
    </CdpProvider>
  </React.StrictMode>,
)

Session End Callbacks

For React applications, there are two ways to handle session end events:

Method 1: Using the useSessionEnd Hook (Recommended for React)

The useSessionEnd hook provides a React-friendly way to handle session lifecycle events:

"use client"
import { useSessionEnd } from "@hcl-cdp-ta/hclcdp-web-sdk-react"

function SessionHandler() {
  useSessionEnd({
    onDeviceSessionEnd: sessionData => {
      console.log("Device session ended:", sessionData)
      // { deviceSessionId: "dev_123", userSessionId: "user_456", reason: "timeout" }
    },
    onUserSessionEnd: sessionData => {
      console.log("User session ended:", sessionData)
      // { deviceSessionId: "dev_123", userSessionId: "user_456", reason: "login" | "logout" | "timeout" }

      if (sessionData.reason === "timeout") {
        alert("Your session has expired due to inactivity")
      }
    },
  })

  return null // This component only handles side effects
}

// Use it in your app layout or any component
export default function App() {
  return (
    <CdpProvider config={config}>
      <SessionHandler />
      {/* Your other components */}
    </CdpProvider>
  )
}

Benefits of the hook approach:

  • More React-like and composable
  • Multiple components can use the hook independently
  • Easier to test
  • No serialization issues with Next.js
  • Better separation of concerns

Note on Session Renewal: The SDK automatically creates a new session if an event is tracked after a session expires. You don't need to manually create sessions - just handle the session end events if you need to notify users or take specific actions.

Method 2: Config-based Callbacks (For Non-React or Simple Cases)

For vanilla JavaScript use or simple scenarios, you can add callbacks to your configuration:

const config: HclCdpConfig = {
  writeKey: "your-write-key",
  cdpEndpoint: "https://your-cdp-endpoint.com",

  // Called when a device session ends (due to inactivity timeout)
  onDeviceSessionEnd: sessionData => {
    console.log("Device session ended:", sessionData)
  },

  // Called when a user session ends (login, logout, or timeout)
  onUserSessionEnd: sessionData => {
    console.log("User session ended:", sessionData)
    if (sessionData.reason === "timeout") {
      showSessionTimeoutModal()
    }
  },
}

Note: In React applications, prefer the useSessionEnd hook over config callbacks to avoid issues with Next.js Server Components.

Session End Reasons

  • timeout: Session ended due to inactivity timeout
  • login: User session ended because user logged in (starts new user session)
  • logout: User session ended because user logged out

2. Use CDP in Your Components

"use client"
import { useCdp, CdpPageEvent } from "@hcl-cdp-ta/hclcdp-web-sdk-react"

export default function ProductPage() {
  const { track, identify, login, logout, getIdentityData, getSessionData } = useCdp()

  const handlePurchase = () => {
    track({
      identifier: "Purchase",
      properties: {
        value: 99.99,
        currency: "USD",
        product_id: "prod-123",
      },
    })
  }

  const handleLogin = () => {
    login({
      identifier: "user-456",
      properties: {
        email: "[email protected]",
        tier: "premium",
      },
    })
  }

  return (
    <div>
      {/* Automatic page tracking */}
      <CdpPageEvent pageName="Product Page" pageProperties={{ product_id: "123", category: "Electronics" }} />

      <h1>Product Page</h1>
      <button onClick={handlePurchase}>Buy Now</button>
      <button onClick={handleLogin}>Login</button>
    </div>
  )
}

API Reference

useCdp() Hook

The main hook for accessing CDP functionality in React components.

const {
  // Core event methods
  track,
  page,
  identify,
  login,
  logout,

  // Data access methods
  getIdentityData,
  getSessionData,
  getDeviceSessionId,
  getUserSessionId,

  // Runtime configuration
  setSessionLogging, // deprecated
  setDeviceSessionLogging,
  setUserSessionLogging,
  setUserLogoutLogging,
  setInactivityTimeout,
  getConfig,

  // State
  isReady,
} = useCdp()

Automatic Cookie Collection

The SDK automatically collects common tracking cookies and includes them in the otherIds section of all events:

  • _ga - Google Analytics client ID
  • _fbc - Facebook Click ID
  • _fbp - Facebook Browser ID
  • mcmid - Adobe Marketing Cloud ID

These cookies are automatically merged with any manually provided otherIds, with manual values taking precedence.

// Automatic cookies included even with empty otherIds
track({
  identifier: "Purchase",
  properties: { value: 99.99 },
  otherIds: {},
})

// Manual otherIds merged with automatic cookies
track({
  identifier: "Purchase",
  properties: { value: 99.99 },
  otherIds: { custom_id: "abc123" },
})

Event Methods

track(event)

Track custom events with properties and additional identifiers.

track({
  identifier: "Button Click",
  properties: {
    button_text: "Subscribe",
    location: "header",
    campaign: "summer-sale",
  },
  otherIds: {
    campaign_id: "camp_123",
  },
})
page(event)

Track page views with custom properties.

page({
  identifier: "Product Details",
  properties: {
    product_id: "123",
    category: "Electronics",
    price: 299.99,
  },
})
identify(event)

Associate events with specific users. Does not create a new user session - keeps existing session IDs.

identify({
  identifier: "user-789",
  properties: {
    email: "[email protected]",
    name: "Jane Smith",
    signup_date: "2024-01-15",
  },
})
login(event)

Start a new user session and identify the user (combines identify + new user session). Creates a new user session ID while preserving the device session.

login({
  identifier: "user-789",
  properties: {
    email: "[email protected]",
    login_method: "social",
    tier: "premium",
  },
})
logout()

Clear user identity and start a new user session (device session continues).

logout()

When to Use identify() vs login()

Use identify() when:

  • User updates their profile information
  • You want to associate events with a user without changing sessions
  • Tracking user behavior within the same session
  • User hasn't actually "logged in" but you know who they are (e.g., from cookies)

Use login() when:

  • User enters credentials and authenticates
  • Starting a fresh user session after login
  • You want session analytics to reflect authentication events
  • User switches between accounts

Data Access Methods

getIdentityData()

Get current identity information.

const identity = getIdentityData()
// {
//   profileId: "prof_abc123",
//   deviceId: "dev_xyz789",
//   userId: "user-456"
// }
getSessionData()

Get current session information with timestamps for both device and user sessions.

const session = getSessionData()
// {
//   deviceSessionId: "dev_sess_abc123",
//   userSessionId: "user_sess_def456",
//   sessionStartTimestamp: 1640995200000,
//   userSessionStartTimestamp: 1640996100000,
//   lastActivityTimestamp: 1640998800000
// }
getDeviceSessionId()

Get the current device session ID (persists across login/logout).

const deviceSessionId = getDeviceSessionId()
// "dev_sess_abc123"
getUserSessionId()

Get the current user session ID (changes on login/logout).

const userSessionId = getUserSessionId()
// "user_sess_def456"

Runtime Configuration Methods

setSessionLogging(enabled)

Enable or disable session start/end event tracking.

setSessionLogging(true) // Start tracking sessions
setSessionLogging(false) // Stop tracking sessions
setUserLogoutLogging(enabled)

Enable or disable user logout event tracking.

setUserLogoutLogging(true) // Track logout events
setUserLogoutLogging(false) // Don't track logout events
setInactivityTimeout(minutes)

Update session timeout with immediate effect.

setInactivityTimeout(60) // 1 hour timeout
setInactivityTimeout(15) // 15 minute timeout
getConfig()

Get current configuration settings.

const config = getConfig()
// Returns current HclCdpConfig object

useSessionEnd() Hook

React hook for handling session lifecycle events. This is the recommended approach for React applications.

import { useSessionEnd } from "@hcl-cdp-ta/hclcdp-web-sdk-react"

useSessionEnd({
  onDeviceSessionEnd?: (sessionData: SessionEndData) => void
  onUserSessionEnd?: (sessionData: SessionEndData) => void
})

Parameters:

  • onDeviceSessionEnd (optional): Callback when device session ends (usually timeout)
  • onUserSessionEnd (optional): Callback when user session ends (login/logout/timeout)

SessionEndData interface:

interface SessionEndData {
  deviceSessionId: string
  userSessionId: string
  reason: "timeout" | "login" | "logout"
}

Example:

"use client"
import { useSessionEnd } from "@hcl-cdp-ta/hclcdp-web-sdk-react"

function SessionManager() {
  useSessionEnd({
    onUserSessionEnd: sessionData => {
      if (sessionData.reason === "timeout") {
        // Handle session timeout
        showSessionExpiredDialog()
        redirectToLogin()
      }
    },
  })

  return null
}

<CdpPageEvent> Component

Declarative component for automatic page tracking.

<CdpPageEvent
  pageName="Home Page"
  pageProperties={{
    section: "landing",
    experiment: "variant-a",
    user_type: "premium",
  }}
/>

Props:

  • pageName (string): Name of the page for tracking
  • pageProperties (object, optional): Additional page-specific properties

Important: While CdpPageEvent can be safely included in server components (it won't cause SSR errors), the actual page tracking only occurs client-side after the component mounts in the browser. This is intentional, as page tracking requires browser APIs like cookies, localStorage, and user session data that are only available on the client.

<CdpProvider> Component

Context provider that initializes and manages the CDP SDK.

<CdpProvider config={cdpConfig}>{/* Your app components */}</CdpProvider>

Props:

  • config (HclCdpConfig): CDP configuration object
  • children (ReactNode): Child components

Configuration

HclCdpConfig Interface

interface HclCdpConfig {
  writeKey: string // Required: Your CDP source write key
  cdpEndpoint: string // Required: Your CDP instance endpoint
  inactivityTimeout?: number // Optional: Session timeout in minutes (default: 30)
  enableSessionLogging?: boolean // Optional: Track session events (default: false)
  enableUserLogoutLogging?: boolean // Optional: Track logout events (default: false)
  destinations?: DestinationConfig[] // Optional: Third-party destinations
}

Destination Configuration

const destinations = [
  {
    id: "GA4",
    classRef: GoogleAnalytics,
    config: { measurementId: "G-XXXXXXXXXX" },
  },
  {
    id: "Facebook",
    classRef: Facebook,
    config: { pixelId: "your-pixel-id" },
  },
]

Advanced Examples

Dynamic Configuration Management

"use client"
import { useCdp } from "@hcl-cdp-ta/hclcdp-web-sdk-react"
import { useState, useEffect } from "react"

export default function ConfigPanel() {
  const { setSessionLogging, setInactivityTimeout, getConfig } = useCdp()

  const [config, setConfig] = useState(getConfig())

  const handleSessionLoggingChange = (enabled: boolean) => {
    setSessionLogging(enabled)
    setConfig(getConfig()) // Update local state
  }

  const handleTimeoutChange = (minutes: number) => {
    setInactivityTimeout(minutes)
    setConfig(getConfig()) // Update local state
  }

  return (
    <div>
      <label>
        <input
          type="checkbox"
          checked={config.enableSessionLogging}
          onChange={e => handleSessionLoggingChange(e.target.checked)}
        />
        Enable Session Logging
      </label>

      <label>
        Session Timeout (minutes):
        <input
          type="number"
          value={config.inactivityTimeout}
          onChange={e => handleTimeoutChange(parseInt(e.target.value))}
        />
      </label>
    </div>
  )
}

Conditional Event Tracking

"use client"
import { useCdp } from "@hcl-cdp-ta/hclcdp-web-sdk-react"
import { useEffect } from "react"

export default function ConditionalTracking() {
  const { track, getIdentityData, isReady } = useCdp()

  useEffect(() => {
    if (isReady) {
      const identity = getIdentityData()

      // Only track for identified users
      if (identity?.userId) {
        track({
          identifier: "Page View - Authenticated",
          properties: {
            user_segment: "premium",
            page_type: "dashboard",
          },
        })
      } else {
        track({
          identifier: "Page View - Anonymous",
          properties: {
            page_type: "landing",
          },
        })
      }
    }
  }, [isReady, track, getIdentityData])

  return <div>Content...</div>
}

E-commerce Tracking

"use client"
import { useCdp } from "@hcl-cdp-ta/hclcdp-web-sdk-react"

export default function CheckoutFlow() {
  const { track, identify } = useCdp()

  const handleAddToCart = (product: any) => {
    track({
      identifier: "Add to Cart",
      properties: {
        product_id: product.id,
        product_name: product.name,
        price: product.price,
        category: product.category,
        quantity: 1,
      },
    })
  }

  const handlePurchase = (order: any) => {
    track({
      identifier: "Purchase",
      properties: {
        order_id: order.id,
        total: order.total,
        currency: "USD",
        items: order.items.map((item: any) => ({
          product_id: item.id,
          quantity: item.quantity,
          price: item.price,
        })),
      },
    })
  }

  const handleUserRegistration = (user: any) => {
    identify({
      identifier: user.id,
      properties: {
        email: user.email,
        name: user.name,
        registration_date: new Date().toISOString(),
        source: "checkout_flow",
      },
    })
  }

  return <div>{/* Your checkout UI */}</div>
}

TypeScript Support

Full TypeScript support with comprehensive type definitions:

import {
  useCdp,
  useSessionEnd,
  CdpProvider,
  CdpPageEvent,
  EventObject,
  IdentityData,
  FullSessionData,
  HclCdpConfig,
} from "@hcl-cdp-ta/hclcdp-web-sdk-react"

// Type-safe event tracking
const trackEvent: EventObject = {
  identifier: "Custom Event",
  properties: {
    custom_property: "value",
  },
  otherIds: {
    external_id: "ext_123",
  },
}

Breaking Changes in v1.0.0

Dual Session Architecture

  • Device Sessions: Persist across login/logout events
  • User Sessions: Reset on login/logout events
  • Event payloads now include both deviceSessionId and userSessionId

Event Payload Structure Changes

Session IDs moved from root level to nested context.session object:

v0.x Format:

{
  sessionId: "sess_123",
  context: { /* other context */ }
}

v1.0.0 Format:

{
  context: {
    session: {
      deviceSessionId: "dev_sess_123",
      userSessionId: "user_sess_456"
    }
  }
}

Configuration Changes

New session logging options:

const config = {
  enableSessionLogging: true, // Still available (logs both)
  enableDeviceSessionLogging: true, // New: device sessions only
  enableUserSessionLogging: true, // New: user sessions only
}

API Method Changes

  • getSessionData() now returns both device and user session information
  • Added getDeviceSessionId() for device session access
  • Added getUserSessionId() for user session access
  • Added login(event) method for user authentication flow

Migration Guide

Step 1: Update Package Version

npm install @hcl-cdp-ta/[email protected]

Step 2: Update Session Data Access

Before (v0.x):

const session = getSessionData()
const sessionId = session.sessionId

After (v1.0.0):

const session = getSessionData()
const deviceSessionId = session.deviceSessionId
const userSessionId = session.userSessionId

// Or use specific getters
const deviceSessionId = getDeviceSessionId()
const userSessionId = getUserSessionId()

Step 3: Update Authentication Flow

Before (v0.x):

// Login
identify({ identifier: "user123", properties: {...} })

// Logout
// No specific logout method

After (v1.0.0):

// Login - creates new user session
login({ identifier: "user123", properties: {...} })

// Logout - clears user session
logout()

Step 4: Update Session Logging Configuration

Before (v0.x):

const config = {
  enableSessionLogging: true,
}

After (v1.0.0):

const config = {
  enableSessionLogging: true, // Logs both session types
  enableDeviceSessionLogging: true, // Optional: device only
  enableUserSessionLogging: true, // Optional: user only
}

Step 5: Test Event Payloads

Verify that your event processing systems handle the new nested session structure in context.session.

Troubleshooting

SSR and Server Components

As of v1.2.0+, both CdpProvider and CdpPageEvent automatically handle server-side rendering (SSR) by detecting the environment and only initializing/tracking on the client side. No additional wrapper components are needed.

Both components use an internal isMounted state to ensure the SDK only initializes and tracks events after the component has mounted in the browser, preventing SSR errors in Next.js and other frameworks.

You can use CdpPageEvent directly in server components:

// app/my-page/page.tsx (Server Component)
import { CdpPageEvent } from "@hcl-cdp-ta/hclcdp-web-sdk-react"

export default function MyServerPage() {
  return (
    <>
      <CdpPageEvent pageName="My Server Page" pageProperties={{ section: "main" }} />
      <h1>Server Component Content</h1>
      {/* Rest of your server component */}
    </>
  )
}

The component will render safely during SSR and automatically track the page event once it mounts on the client.

Related Packages

Requirements

  • React 16.8+ (hooks support)
  • Next.js 12+ (for Next.js projects)
  • TypeScript 4.0+ (for TypeScript projects)

Contributing

We welcome contributions! Please read our CONTRIBUTING.md for details on:

  • Commit Message Format: This project uses Conventional Commits
  • Automated Validation: Commit messages are validated locally and in CI/CD
  • Release Process: Automatic versioning and changelog generation via Release Please

Quick reference for commit types:

  • feat: - New feature (minor version bump)
  • fix: - Bug fix (patch version bump)
  • feat!: or BREAKING CHANGE: - Breaking change (major version bump)
  • docs:, style:, refactor:, perf:, test:, build:, ci:, chore:

Example: feat: add useSessionEnd hook

License

This project is licensed under the MIT License.