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

@rcigroup/horizon-analytics-sdk

v0.2.2

Published

Browser-focused analytics SDK for Horizon products.

Readme

@rcigroup/horizon-analytics-sdk

Browser-focused analytics SDK for Horizon products.

Installation

npm install @rcigroup/horizon-analytics-sdk

Exposed API

The package exposes these methods:

  • configureAnalytics
  • recordEvent
  • recordRichEvent
  • validateEvent
  • analyticsTargets — common target/action constants (see below)

Configuration

Consumers only need to configure application metadata once:

import { configureAnalytics } from "@rcigroup/horizon-analytics-sdk";

configureAnalytics({
  context: {
    app: {
      name: "Horizon Console",
      version: "9.1.0",
    },
  },
});

Event Contract

Every emitted payload uses schema 2.0.0 and is shaped as:

{
  "schema": "2.0.0",
  "context": {
    "sdk": {
      "name": "horizon-analytics-sdk",
      "version": "0.1.0"
    },
    "app": {
      "name": "Horizon Console",
      "version": "9.1.0"
    },
    "device": {
      "agent": "Mozilla/5.0 ...",
      "os": "macOS",
      "agent-raw": {
        "brands": [{ "brand": "Chromium", "version": "136" }],
        "mobile": false,
        "platform": "macOS"
      }
    },
    "user": {
      "name": "Jake Brown",
      "id": "user-42",
      "email": "[email protected]",
      "token": "SUPABASE_ACCESS_TOKEN"
    },
    "session": {
      "id": "session-live-123"
    }
  },
  "events": [
    {
      "id": "01977e8f-4d50-7cc8-9d54-7ce5f6d0e580",
      "target": "checkout-button",
      "action": "click",
      "timestamp": "2026-01-01T10:00:00.000+00:00",
      "location": {
        "origin": "app.horizon.local",
        "route": "/checkout"
      },
      "payload": {
        "plan": "pro"
      }
    }
  ]
}

Context Hydration

The SDK automatically populates:

  • context.sdk.name as horizon-analytics-sdk
  • context.sdk.version from the package version injected by Vite at build/publish time via __SDK_VERSION__
  • context.device.* from browser globals when available
  • events[0].id with a UUIDv7
  • events[0].timestamp with the local timezone offset
  • events[0].location.origin and events[0].location.route

recordRichEvent also hydrates context.user and context.session from Supabase user/session objects when available. If optional browser or Supabase fields are unavailable, the SDK emits null for those context values and falls back to "unknown" origin or "/" route in non-browser environments.

Origin Normalization

The SDK automatically strips the URL scheme from origin values during recording. For example, https://app.horizon.local is recorded as app.horizon.local. This happens transparently — callers do not need to change existing call sites.

Backend Delivery

recordEvent and recordRichEvent always send every valid event envelope to the analytics backend.

  • Default backend endpoint:

https://ufptzleifvxclheanssz.supabase.co/functions/v1/vision-ingest-event

  • If the backend returns a non-200 status, the SDK logs a warning to console.warn.
  • The SDK does not retry failed requests.

You can override the backend URL globally in your app:

import { setAnalyticsBackendUrl } from "@rcigroup/horizon-analytics-sdk";

setAnalyticsBackendUrl("https://analytics.example.com/events");

If you do not set a URL, the default endpoint above is used.

Common Targets and Actions

analyticsTargets is a typed helper that provides common target/action name constants with full TypeScript autocomplete:

import { analyticsTargets, recordEvent } from "@rcigroup/horizon-analytics-sdk";

// Use a common target and action from the helper
recordEvent({
  target: "authentication",
  action: analyticsTargets.authentication.login,
});

recordEvent({
  target: "page",
  action: analyticsTargets.page.load,
});

recordEvent({
  target: "form",
  action: analyticsTargets.form["validation-fail"],
});

Available targets and their actions:

| Target | Actions | | ---------------- | ---------------------------------------------- | | authentication | login, refresh, logout | | authorization | deny, grant | | page | load, redirect | | file | upload, download | | performance | slow, timeout | | form | submit_success, submit_fail, validation-fail | | configuration | update |

Consumers can also pass any arbitrary string for target and action — the helper is additive and does not constrain the API:

recordEvent({
  target: "my-custom-widget",
  action: "custom-interaction",
});

Usage

import {
  analyticsTargets,
  configureAnalytics,
  recordEvent,
  recordRichEvent,
  validateEvent,
} from "@rcigroup/horizon-analytics-sdk";

configureAnalytics({
  context: {
    app: {
      name: "Horizon Console",
      version: "9.1.0",
    },
  },
});

// Using the common targets/actions helper
const loginEvent = recordEvent({
  target: "authentication",
  action: analyticsTargets.authentication.login,
});

// Using custom target and action strings
const anonymousEvent = recordEvent({
  target: "checkout-button",
  action: "click",
  payload: {
    plan: "pro",
    amount: 4999,
  },
});

const authenticatedEvent = recordRichEvent({
  target: "account-link",
  action: "click",
  payload: {
    placement: "header",
  },
  user: {
    id: "user-42",
    email: "[email protected]",
    user_metadata: {
      full_name: "Jake Brown",
    },
  },
  session: {
    id: "session-live-123",
    access_token: "SUPABASE_ACCESS_TOKEN",
  },
});

for (const event of [loginEvent, anonymousEvent, authenticatedEvent]) {
  const validation = validateEvent(event);

  if (!validation.valid) {
    console.error(validation.errors);
  }
}

Development

npm run build
npm run test
npm run typecheck
npm run lint