Skip to main content

Product analytics

Gainsight PX

The gainsightPx helper waits for measurement consent before it creates window.aptrinsic or requests the PX SDK. This gate covers both product analytics and in-app engagements. On revocation, the helper disables the tag through PX's config API and requests a session reset.

Configure Gainsight PX

Copy the product/channel key from Administration > Products in Gainsight PX. Remove any existing PX snippet or tag-manager installation so it cannot load outside c15t.

npm install @c15t/integrations
src/consent-scripts.ts
import { gainsightPx } from '@c15t/integrations/gainsight-px';

export const scripts = [gainsightPx({ productKey: 'AP-PRODUCT-KEY-2' })];

Register the scripts

Complete your framework quickstart first. Keep its Inth endpoint, policy, styles and consent UI. Remove the vendor's original script, SDK initializer or tag-manager entry, so the vendor loads only through c15t.

The vendor pages put the helper in src/consent-scripts.ts. If your framework quickstart already has a scripts array, such as the one in c15t.config.ts in the Next.js guide, add the helper to that array instead of creating a second file. The scripts export is a configuration, not an initializer. Add it to the c15t provider you already have, at the registration point for your framework below. These are edits to that provider, not a second provider.

Add the configuration to scripts in c15t.config.ts, next to next.config.ts:

import { defineConsentConfig } from 'c15t/next';
import { scripts } from './src/consent-scripts';

export default defineConsentConfig({ scripts });

Keep the rest of your config, such as mode and routePrefix, in the same call. ConsentRoot reads the config in the browser, so the layout keeps passing only state. App Router, Pages Router and static export all read the same file. See Next.js scripts and embeds.

Options

OptionDefaultBehavior
productKeyRequiredProduct/channel key assigned to aptrinsic.p and the loader's a query parameter. Changing the key after this helper starts PX throws an error and requires a page reload. Blank values log an error and skip installation.
categorymeasurementConsent category or condition for the whole SDK. Choose experience if it fits your use of analytics and engagements.
configNoneJSON-serializable PX startup configuration assigned to aptrinsic.c. Changing it after PX starts throws and requires a page reload. c15t owns enableTag; do not set it yourself.
userNoneUser identify payload with a required id. The helper queues it only after mapped consent.
accountNoneOptional account identify payload with a required id. Sent only when user is also supplied.
scriptUrlhttps://web-sdk.aptrinsic.com/api/aptrinsic.js?a=<productKey>Full loader override. Other PX requests still use the endpoints configured by the SDK.

config supports PX options such as fullDomainCookie, localStorageCookie, usePOST and htmlSanitization. Keep configuration and identity data JSON-serializable. Send dates as epoch milliseconds. For custom attributes, use the API names from Administration > Attributes.

// Options for gainsightPx in src/consent-scripts.ts.
{
	productKey: 'AP-PRODUCT-KEY-2',
	category: 'experience',
	config: { fullDomainCookie: true },
	user: { id: 'user-123', plan: 'paid' },
	account: { id: 'account-456' },
}

The optional identity is part of the script configuration. For a later login or account change, call PX's identify API only while the visitor still permits this vendor. c15t does not gate event calls made elsewhere in your application.

Loading and revocation

Before mapped consent, the helper creates no PX global, loader, cookies or localStorage entries. It does not load PX with enableTag: false as an early-loading mode.

After consent, the helper creates the official function queue with p for the product key and c for configuration. It enables the tag, optionally queues identify, then appends the asynchronous loader. PX may begin anonymous tracking before its queued identify call completes.

When mapped consent is withdrawn, the helper sends aptrinsic('config', 'enableTag', false) followed by aptrinsic('reset') and removes the loader element if it is still downloading or failed to load. After the loader's load event, the helper retains the element. Gainsight documents enableTag: false as stopping PX cookies, network calls and engagements. Its current SDK resets the session inside the disable call and ignores a separate reset while disabled.

If reloadOnConsentRevoked is disabled, granting consent again after a completed load sends aptrinsic('config', 'enableTag', true) and repeats the optional identify call through the existing API. The helper reuses the loaded SDK because PX rejects a second execution of its bundle. A loader removed before completion can be requested again on a later grant if PX has not started executing it.

Before requesting another pending load, the helper rebuilds its function queue from the current options. The new queue contains only the current product, configuration and optional identity, so an interrupted setup cannot replay an earlier user's identify call. This also applies to server-generated startup. It does not cancel a detached download that may still execute later.

When hydrating a server-started loader, use the same productKey, config, user, account and scriptUrl on the server and client. The loader compares the server setup with the client options before adopting the server's element. This check also runs when PX finishes startup before hydration. c15t retains the startup settings separately from PX's queue so the check still works after PX replaces its function stub. A mismatch throws before registration or replacement and leaves the existing setup intact. If identity changes between render and hydration, reload the page with the current options. Matching options preserve the existing SDK and loader. Equivalent configuration objects can use different property orders.

Disposing the last provider or script loader removes its element, but PX's code remains in the page. Later mounts check PX's own bundle execution marker and use the existing API without requesting the bundle again. A denied mount sends disable and reset commands without enabling PX or identifying the user. A later grant enables the tag and repeats the optional identify call. An aptrinsic queue alone does not prove that the SDK ran. The runtime check also survives customization with object spread, such as { ...gainsightPx(options), anonymizeId: false }, even when the copy was made before PX started and the same copy is mounted again after disposal. Creating a fresh spread copy with equivalent options on each rerender also preserves a pending loader and its queued setup.

Once this helper starts the SDK, use the same productKey for the rest of the page's lifetime, including after disposal. Constructing a helper with another key throws an error. The loader also rejects a different-key script created before startup if it is registered after PX starts, preserving the current configuration and its consent handling. Reload the page before installing a different product. PX's asynchronous tagKey API queues commands during reconfiguration and can defer opt-out until after queued identity calls, so c15t does not use it.

Keep the same config after startup too, including after disposal. Adding, removing or changing a configuration value throws before registration or replacement, so the current consent handling stays active. This also applies to scripts created before startup and registered afterward. Equivalent objects may use a different property order. The reuse path forwards consent and optional identity calls; it does not apply new startup settings through PX's config API. Reload the page to change configuration.

PX has one global SDK per window. Mount one configuration at a time. Owners with different options still control the same SDK and do not share a consent veto. Equivalent configurations can share owners.

Disposal itself does not disable PX or stop its timers and listeners. Keep a consent owner mounted while the SDK is in use so it can forward revocation.

Keep reloadOnConsentRevoked enabled. Removing a pending loader does not unload PX's code or cancel requests that already started. A load that finishes after revocation may still execute vendor code. The helper queues the stop request, but a page reload ends the SDK's timers and listeners. If consent returns before that detached download executes, a new loader can race with it and PX can reject the duplicate bundle. This helper does not guarantee that every PX feature resumes after another grant without a reload. Verify recovery with your product key, SDK version and enabled features.

Cookies and storage

Gainsight documents these first-party cookies:

NameLifetimePurpose
apt.uid1 yearPersistent visitor identity.
apt.sid30 minutes of inactivityCurrent session identity.

fullDomainCookie: true scopes cookie data to the full hostname rather than the top-level domain. localStorageCookie: true moves cookie data to localStorage. These settings change where PX persists data; they do not replace the consent gate. Inspect storage for your configured PX version and features.

Verify Gainsight PX

In a private window, deny analytics and confirm there is no request to web-sdk.aptrinsic.com or esp.aptrinsic.com, no window.aptrinsic, and no apt.uid or apt.sid storage. Allow the category selected by category, then check that the SDK loads and your PX product receives the expected events. Revoke that category and confirm the reloaded page makes no PX request.

The helper already sends PX's documented opt-out command. The shared advice about adding a custom stop callback applies when you need more cleanup than this command provides.

Test in a private window with an opt-in policy. Open DevTools Network, disable the cache and filter by the vendor's domain:

  1. Load the page. No request goes to the vendor before you choose.
  2. Click Reject, then reload. There is still no vendor request.
  3. Open Privacy settings and allow the helper's category. The vendor script loads without a page reload.
  4. Turn the category off again and save. c15t reloads the page, and the new page makes no vendor request.

c15t reloads on revocation because removing a script element does not stop code that already ran. The vendor's listeners, timers and queued events stay alive until the page unloads. If you set reloadOnConsentRevoked: false, stop the vendor yourself. Register a callback-only script whose onConsentChange calls the vendor's opt-out API, as shown in custom integrations, and check the permission before each of your own event calls. The reload does not delete cookies the vendor already set; see clear on revocation for your framework.

The helper lists its vendor by name in the preference dialog, so a visitor can turn it off inside an allowed category. See vendor consent for your framework. The consent verification guide covers navigation, expiry and hosting checks.

Official sources