Contentful Personalization & Analytics
    Preparing search index...

    Client for sending analytics and insights events to the Ninetailed Insights API.

    This client is optimized for sending batched events, optionally using a custom beacon-like sender for last-chance lifecycle delivery.

    const insightsClient = new InsightsApiClient({
    spaceId: 'space-id',
    environment: 'master',
    })

    await insightsClient.sendBatchEvents([
    {
    profile: { id: 'profile-123', ... },
    events: [
    {
    type: 'track',
    event: 'button_clicked',
    properties: { id: 'primary-cta' },
    },
    ],
    }
    ])

    Extends ApiClientBase.

    Hierarchy

    • ApiClientBase
      • InsightsApiClient
    Index

    Constructors

    Properties

    baseUrl: string

    Base URL used for Insights API requests.

    environment: string

    Contentful space environment associated with this client.

    Protected fetch method used by the client to perform HTTP requests.

    name: string

    Name of the API client, used in log messages and as the apiName for fetch.

    spaceId: string

    Contentful Space identifier used for authentication or tracking.

    Methods

    • Logs errors that occur during API requests with standardized messages.

      Parameters

      • error: unknown

        The error thrown by the underlying operation.

      • options: { requestName: string }

        Additional metadata about the request.

        • requestName: string

          Human-readable name of the request operation.

      Returns void

      Abort errors are logged at warn level and other errors at error level. The log message includes the client name for better debugging context.

    • Sends batches of insights events to the Ninetailed Insights API.

      Parameters

      • batches: {
            events: (
                | {
                    channel: "server"
                    | "mobile"
                    | "web";
                    context: {
                        app?: { name: string; version: string };
                        campaign: {
                            content?: string;
                            medium?: string;
                            name?: string;
                            source?: string;
                            term?: string;
                        };
                        gdpr: { isConsentGiven: boolean };
                        library: { name: string; version: string };
                        locale: string;
                        location?: {
                            city?: string;
                            continent?: string;
                            coordinates?: { latitude: number; longitude: number };
                            country?: string;
                            countryCode?: string;
                            postalCode?: string;
                            region?: string;
                            regionCode?: string;
                            timezone?: string;
                        };
                        page?: {
                            path: string;
                            query: Record<string, string>;
                            referrer: string;
                            search: string;
                            title?: string;
                            url: string;
                            [key: string]: JSONType;
                        };
                        screen?: { name: string; [key: string]: JSONType };
                        userAgent?: string;
                    };
                    entityId: string;
                    entityKind: | "Experience"
                    | "Fragment"
                    | "InlineFragment"
                    | "InlineComponent";
                    entityKindId?: string;
                    entryIds?: string[];
                    messageId: string;
                    optimizationId?: string;
                    originalTimestamp: string;
                    parameters?: Record<string, JSONType>;
                    parentExperienceId?: string;
                    sentAt: string;
                    timestamp: string;
                    type: "exo_node_view";
                    userId?: string;
                    variantId?: string;
                    variantIndex?: number;
                    viewDurationMs: number;
                    viewId: string;
                }
                | {
                    channel: "server"
                    | "mobile"
                    | "web";
                    componentId: string;
                    componentType: "Entry" | "Variable";
                    context: {
                        app?: { name: string; version: string };
                        campaign: {
                            content?: string;
                            medium?: string;
                            name?: string;
                            source?: string;
                            term?: string;
                        };
                        gdpr: { isConsentGiven: boolean };
                        library: { name: string; version: string };
                        locale: string;
                        location?: {
                            city?: string;
                            continent?: string;
                            coordinates?: { latitude: number; longitude: number };
                            country?: string;
                            countryCode?: string;
                            postalCode?: string;
                            region?: string;
                            regionCode?: string;
                            timezone?: string;
                        };
                        page?: {
                            path: string;
                            query: Record<string, string>;
                            referrer: string;
                            search: string;
                            title?: string;
                            url: string;
                            [key: string]: JSONType;
                        };
                        screen?: { name: string; [key: string]: JSONType };
                        userAgent?: string;
                    };
                    experienceId?: string;
                    messageId: string;
                    originalTimestamp: string;
                    sentAt: string;
                    timestamp: string;
                    type: "component";
                    userId?: string;
                    variantIndex: number;
                    viewDurationMs?: number;
                    viewId?: string;
                }
                | {
                    channel: "server"
                    | "mobile"
                    | "web";
                    componentId: string;
                    componentType: "Entry" | "Variable";
                    context: {
                        app?: { name: string; version: string };
                        campaign: {
                            content?: string;
                            medium?: string;
                            name?: string;
                            source?: string;
                            term?: string;
                        };
                        gdpr: { isConsentGiven: boolean };
                        library: { name: string; version: string };
                        locale: string;
                        location?: {
                            city?: string;
                            continent?: string;
                            coordinates?: { latitude: number; longitude: number };
                            country?: string;
                            countryCode?: string;
                            postalCode?: string;
                            region?: string;
                            regionCode?: string;
                            timezone?: string;
                        };
                        page?: {
                            path: string;
                            query: Record<string, string>;
                            referrer: string;
                            search: string;
                            title?: string;
                            url: string;
                            [key: string]: JSONType;
                        };
                        screen?: { name: string; [key: string]: JSONType };
                        userAgent?: string;
                    };
                    experienceId?: string;
                    messageId: string;
                    originalTimestamp: string;
                    sentAt: string;
                    timestamp: string;
                    type: "component_click";
                    userId?: string;
                    variantIndex: number;
                }
                | {
                    channel: "server"
                    | "mobile"
                    | "web";
                    context: {
                        app?: { name: string; version: string };
                        campaign: {
                            content?: string;
                            medium?: string;
                            name?: string;
                            source?: string;
                            term?: string;
                        };
                        gdpr: { isConsentGiven: boolean };
                        library: { name: string; version: string };
                        locale: string;
                        location?: {
                            city?: string;
                            continent?: string;
                            coordinates?: { latitude: number; longitude: number };
                            country?: string;
                            countryCode?: string;
                            postalCode?: string;
                            region?: string;
                            regionCode?: string;
                            timezone?: string;
                        };
                        page?: {
                            path: string;
                            query: Record<string, string>;
                            referrer: string;
                            search: string;
                            title?: string;
                            url: string;
                            [key: string]: JSONType;
                        };
                        screen?: { name: string; [key: string]: JSONType };
                        userAgent?: string;
                    };
                    entityId: string;
                    entityKind: | "Experience"
                    | "Fragment"
                    | "InlineFragment"
                    | "InlineComponent";
                    entityKindId?: string;
                    entryIds?: string[];
                    messageId: string;
                    optimizationId?: string;
                    originalTimestamp: string;
                    parameters?: Record<string, JSONType>;
                    parentExperienceId?: string;
                    sentAt: string;
                    timestamp: string;
                    type: "exo_node_click";
                    userId?: string;
                    variantId?: string;
                    variantIndex?: number;
                }
                | {
                    channel: "server"
                    | "mobile"
                    | "web";
                    context: {
                        app?: { name: string; version: string };
                        campaign: {
                            content?: string;
                            medium?: string;
                            name?: string;
                            source?: string;
                            term?: string;
                        };
                        gdpr: { isConsentGiven: boolean };
                        library: { name: string; version: string };
                        locale: string;
                        location?: {
                            city?: string;
                            continent?: string;
                            coordinates?: { latitude: number; longitude: number };
                            country?: string;
                            countryCode?: string;
                            postalCode?: string;
                            region?: string;
                            regionCode?: string;
                            timezone?: string;
                        };
                        page?: {
                            path: string;
                            query: Record<string, string>;
                            referrer: string;
                            search: string;
                            title?: string;
                            url: string;
                            [key: string]: JSONType;
                        };
                        screen?: { name: string; [key: string]: JSONType };
                        userAgent?: string;
                    };
                    entityId: string;
                    entityKind: | "Experience"
                    | "Fragment"
                    | "InlineFragment"
                    | "InlineComponent";
                    entityKindId?: string;
                    entryIds?: string[];
                    hoverDurationMs: number;
                    hoverId: string;
                    messageId: string;
                    optimizationId?: string;
                    originalTimestamp: string;
                    parameters?: Record<string, JSONType>;
                    parentExperienceId?: string;
                    sentAt: string;
                    timestamp: string;
                    type: "exo_node_hover";
                    userId?: string;
                    variantId?: string;
                    variantIndex?: number;
                }
                | {
                    channel: "server"
                    | "mobile"
                    | "web";
                    componentId: string;
                    componentType: "Entry" | "Variable";
                    context: {
                        app?: { name: string; version: string };
                        campaign: {
                            content?: string;
                            medium?: string;
                            name?: string;
                            source?: string;
                            term?: string;
                        };
                        gdpr: { isConsentGiven: boolean };
                        library: { name: string; version: string };
                        locale: string;
                        location?: {
                            city?: string;
                            continent?: string;
                            coordinates?: { latitude: number; longitude: number };
                            country?: string;
                            countryCode?: string;
                            postalCode?: string;
                            region?: string;
                            regionCode?: string;
                            timezone?: string;
                        };
                        page?: {
                            path: string;
                            query: Record<string, string>;
                            referrer: string;
                            search: string;
                            title?: string;
                            url: string;
                            [key: string]: JSONType;
                        };
                        screen?: { name: string; [key: string]: JSONType };
                        userAgent?: string;
                    };
                    experienceId?: string;
                    hoverDurationMs: number;
                    hoverId: string;
                    messageId: string;
                    originalTimestamp: string;
                    sentAt: string;
                    timestamp: string;
                    type: "component_hover";
                    userId?: string;
                    variantIndex: number;
                }
            )[];
            profile: { id: string; [key: string]: JSONType };
        }[]

        Array of event batches to send.

        • events: (
              | {
                  channel: "server"
                  | "mobile"
                  | "web";
                  context: {
                      app?: { name: string; version: string };
                      campaign: {
                          content?: string;
                          medium?: string;
                          name?: string;
                          source?: string;
                          term?: string;
                      };
                      gdpr: { isConsentGiven: boolean };
                      library: { name: string; version: string };
                      locale: string;
                      location?: {
                          city?: string;
                          continent?: string;
                          coordinates?: { latitude: number; longitude: number };
                          country?: string;
                          countryCode?: string;
                          postalCode?: string;
                          region?: string;
                          regionCode?: string;
                          timezone?: string;
                      };
                      page?: {
                          path: string;
                          query: Record<string, string>;
                          referrer: string;
                          search: string;
                          title?: string;
                          url: string;
                          [key: string]: JSONType;
                      };
                      screen?: { name: string; [key: string]: JSONType };
                      userAgent?: string;
                  };
                  entityId: string;
                  entityKind: | "Experience"
                  | "Fragment"
                  | "InlineFragment"
                  | "InlineComponent";
                  entityKindId?: string;
                  entryIds?: string[];
                  messageId: string;
                  optimizationId?: string;
                  originalTimestamp: string;
                  parameters?: Record<string, JSONType>;
                  parentExperienceId?: string;
                  sentAt: string;
                  timestamp: string;
                  type: "exo_node_view";
                  userId?: string;
                  variantId?: string;
                  variantIndex?: number;
                  viewDurationMs: number;
                  viewId: string;
              }
              | {
                  channel: "server"
                  | "mobile"
                  | "web";
                  componentId: string;
                  componentType: "Entry" | "Variable";
                  context: {
                      app?: { name: string; version: string };
                      campaign: {
                          content?: string;
                          medium?: string;
                          name?: string;
                          source?: string;
                          term?: string;
                      };
                      gdpr: { isConsentGiven: boolean };
                      library: { name: string; version: string };
                      locale: string;
                      location?: {
                          city?: string;
                          continent?: string;
                          coordinates?: { latitude: number; longitude: number };
                          country?: string;
                          countryCode?: string;
                          postalCode?: string;
                          region?: string;
                          regionCode?: string;
                          timezone?: string;
                      };
                      page?: {
                          path: string;
                          query: Record<string, string>;
                          referrer: string;
                          search: string;
                          title?: string;
                          url: string;
                          [key: string]: JSONType;
                      };
                      screen?: { name: string; [key: string]: JSONType };
                      userAgent?: string;
                  };
                  experienceId?: string;
                  messageId: string;
                  originalTimestamp: string;
                  sentAt: string;
                  timestamp: string;
                  type: "component";
                  userId?: string;
                  variantIndex: number;
                  viewDurationMs?: number;
                  viewId?: string;
              }
              | {
                  channel: "server"
                  | "mobile"
                  | "web";
                  componentId: string;
                  componentType: "Entry" | "Variable";
                  context: {
                      app?: { name: string; version: string };
                      campaign: {
                          content?: string;
                          medium?: string;
                          name?: string;
                          source?: string;
                          term?: string;
                      };
                      gdpr: { isConsentGiven: boolean };
                      library: { name: string; version: string };
                      locale: string;
                      location?: {
                          city?: string;
                          continent?: string;
                          coordinates?: { latitude: number; longitude: number };
                          country?: string;
                          countryCode?: string;
                          postalCode?: string;
                          region?: string;
                          regionCode?: string;
                          timezone?: string;
                      };
                      page?: {
                          path: string;
                          query: Record<string, string>;
                          referrer: string;
                          search: string;
                          title?: string;
                          url: string;
                          [key: string]: JSONType;
                      };
                      screen?: { name: string; [key: string]: JSONType };
                      userAgent?: string;
                  };
                  experienceId?: string;
                  messageId: string;
                  originalTimestamp: string;
                  sentAt: string;
                  timestamp: string;
                  type: "component_click";
                  userId?: string;
                  variantIndex: number;
              }
              | {
                  channel: "server"
                  | "mobile"
                  | "web";
                  context: {
                      app?: { name: string; version: string };
                      campaign: {
                          content?: string;
                          medium?: string;
                          name?: string;
                          source?: string;
                          term?: string;
                      };
                      gdpr: { isConsentGiven: boolean };
                      library: { name: string; version: string };
                      locale: string;
                      location?: {
                          city?: string;
                          continent?: string;
                          coordinates?: { latitude: number; longitude: number };
                          country?: string;
                          countryCode?: string;
                          postalCode?: string;
                          region?: string;
                          regionCode?: string;
                          timezone?: string;
                      };
                      page?: {
                          path: string;
                          query: Record<string, string>;
                          referrer: string;
                          search: string;
                          title?: string;
                          url: string;
                          [key: string]: JSONType;
                      };
                      screen?: { name: string; [key: string]: JSONType };
                      userAgent?: string;
                  };
                  entityId: string;
                  entityKind: | "Experience"
                  | "Fragment"
                  | "InlineFragment"
                  | "InlineComponent";
                  entityKindId?: string;
                  entryIds?: string[];
                  messageId: string;
                  optimizationId?: string;
                  originalTimestamp: string;
                  parameters?: Record<string, JSONType>;
                  parentExperienceId?: string;
                  sentAt: string;
                  timestamp: string;
                  type: "exo_node_click";
                  userId?: string;
                  variantId?: string;
                  variantIndex?: number;
              }
              | {
                  channel: "server"
                  | "mobile"
                  | "web";
                  context: {
                      app?: { name: string; version: string };
                      campaign: {
                          content?: string;
                          medium?: string;
                          name?: string;
                          source?: string;
                          term?: string;
                      };
                      gdpr: { isConsentGiven: boolean };
                      library: { name: string; version: string };
                      locale: string;
                      location?: {
                          city?: string;
                          continent?: string;
                          coordinates?: { latitude: number; longitude: number };
                          country?: string;
                          countryCode?: string;
                          postalCode?: string;
                          region?: string;
                          regionCode?: string;
                          timezone?: string;
                      };
                      page?: {
                          path: string;
                          query: Record<string, string>;
                          referrer: string;
                          search: string;
                          title?: string;
                          url: string;
                          [key: string]: JSONType;
                      };
                      screen?: { name: string; [key: string]: JSONType };
                      userAgent?: string;
                  };
                  entityId: string;
                  entityKind: | "Experience"
                  | "Fragment"
                  | "InlineFragment"
                  | "InlineComponent";
                  entityKindId?: string;
                  entryIds?: string[];
                  hoverDurationMs: number;
                  hoverId: string;
                  messageId: string;
                  optimizationId?: string;
                  originalTimestamp: string;
                  parameters?: Record<string, JSONType>;
                  parentExperienceId?: string;
                  sentAt: string;
                  timestamp: string;
                  type: "exo_node_hover";
                  userId?: string;
                  variantId?: string;
                  variantIndex?: number;
              }
              | {
                  channel: "server"
                  | "mobile"
                  | "web";
                  componentId: string;
                  componentType: "Entry" | "Variable";
                  context: {
                      app?: { name: string; version: string };
                      campaign: {
                          content?: string;
                          medium?: string;
                          name?: string;
                          source?: string;
                          term?: string;
                      };
                      gdpr: { isConsentGiven: boolean };
                      library: { name: string; version: string };
                      locale: string;
                      location?: {
                          city?: string;
                          continent?: string;
                          coordinates?: { latitude: number; longitude: number };
                          country?: string;
                          countryCode?: string;
                          postalCode?: string;
                          region?: string;
                          regionCode?: string;
                          timezone?: string;
                      };
                      page?: {
                          path: string;
                          query: Record<string, string>;
                          referrer: string;
                          search: string;
                          title?: string;
                          url: string;
                          [key: string]: JSONType;
                      };
                      screen?: { name: string; [key: string]: JSONType };
                      userAgent?: string;
                  };
                  experienceId?: string;
                  hoverDurationMs: number;
                  hoverId: string;
                  messageId: string;
                  originalTimestamp: string;
                  sentAt: string;
                  timestamp: string;
                  type: "component_hover";
                  userId?: string;
                  variantIndex: number;
              }
          )[]

          Insights events to record for this profile.

        • profile: { id: string; [key: string]: JSONType }

          Partial profile information used to associate events with a user.

          • id: string

            Identifier of the profile.

            Used to associate events with an existing profile.

      • options: InsightsApiClientRequestOptions = {}

        Optional request options, including a per-call beacon sender.

      Returns Promise<boolean>

      true when the event batch is successfully queued by the beacon sender or a direct request is successfully sent, false otherwise.

      If a beacon sender is provided, it will be invoked first with the serialized request body. When the sender returns true, the events are considered successfully queued and no network request is made by this method.

      If the sender is missing, returns false, or throws, the events are emitted immediately via fetch.

      const success = await insightsClient.sendBatchEvents(batches)
      
      // Use Beacon for a last-chance lifecycle flush
      const success = await insightsClient.sendBatchEvents(batches, {
      beacon: (url, body) => navigator.sendBeacon(url, body),
      })