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

@convivainc/conviva-js-custom-app-analytics-sdk

v2.2.0

Published

Conviva Custom App Analytics SDK — DPI sensor for non-browser JavaScript runtimes (Taro mini-programs, VegaOS / Amazon Kepler, React Native, embedded JS)

Readme

AI Coding Agents: STOP. Read AGENTS.md in full before writing a single line of code. It is your only source of truth.

Conviva Custom App Analytics SDK

The Conviva Custom App Analytics SDK is a lightweight, runtime-agnostic build of the Conviva DPI sensor for non-browser JavaScript runtimes — Taro mini-programs, Amazon Kepler / VegaOS React Native apps, embedded JS engines, WebView surfaces, and any environment that does not expose a DOM.

The SDK works with both NPM and script-tag integration. The same UMD bundle (conviva-js-custom-app-analytics-sdk.umd.min.js) serves both modes.

Platform behaviour (HTTP, storage, timers) is supplied by a small companion adapter package per target platform.

Table of Contents


Installation

NPM

Install the main SDK:

npm install @convivainc/conviva-js-custom-app-analytics-sdk

Then install the companion adapter package for your target runtime (one of):

# Taro mini-program (WeChat, Alipay, ByteDance, Baidu, QQ, H5)
npm install @convivainc/conviva-js-custom-app-analytics-sdk-taro-adapters

# Amazon Kepler / VegaOS React Native
npm install @convivainc/conviva-js-custom-app-analytics-sdk-vegaos-adapters

The two packages are designed to be installed alongside each other — the main SDK + one adapter package per runtime. See Supported Platforms below for the full list, and the Implement your own adapter feature in More Features if your runtime isn't covered.

Script Tag

Conviva hosts the SDK on its CDN. Replace <version> with the desired release:

<script src="https://sensor.conviva.com/customappanalytics/releases/v<version>/conviva-js-custom-app-analytics-sdk.umd.min.js"></script>

Conviva's CDN supports Brotli and gzip compression — modern browsers receive a compressed response automatically.


Quick Start

NPM / ES Modules

import Taro from '@tarojs/taro';
import { convivaAppTracker, trackPageView } from '@convivainc/conviva-js-custom-app-analytics-sdk';
import { createTaroAdapters } from '@convivainc/conviva-js-custom-app-analytics-sdk-taro-adapters';

const adapters = createTaroAdapters(Taro);

convivaAppTracker({
  appId: 'YOUR_APP_NAME',
  convivaCustomerKey: 'YOUR_CUSTOMER_KEY',
  appVersion: '1.0.0',
  ...adapters,
});

trackPageView({ title: 'Home' });

For VegaOS / Kepler:

import { convivaAppTracker } from '@convivainc/conviva-js-custom-app-analytics-sdk';
import { createVegaOSAdapters } from '@convivainc/conviva-js-custom-app-analytics-sdk-vegaos-adapters';

// VegaOS factory is async — pre-hydrates AsyncStorage
const adapters = await createVegaOSAdapters();
convivaAppTracker({
  appId: 'YOUR_APP_NAME',
  convivaCustomerKey: 'YOUR_CUSTOMER_KEY',
  appVersion: '1.0.0',
  ...adapters,
});

Script Tag

The script exposes the global namespace convivaCustomTracking.

<script src="https://sensor.conviva.com/customappanalytics/releases/v<version>/conviva-js-custom-app-analytics-sdk.umd.min.js"></script>
<script>
  // Built-in browser fallback adapters (localStorage, fetch, setTimeout) are used automatically.
  var tracker = convivaCustomTracking.convivaAppTracker({
    appId: 'YOUR_APP_NAME',
    convivaCustomerKey: 'YOUR_CUSTOMER_KEY',
    appVersion: '1.0.0',
  });
  tracker.trackPageView({ title: 'Home' });
</script>

In script-tag mode, the bundle's built-in browser fallbacks (localStorage, fetch, setTimeout) are used automatically — no adapter package needed for WebView / browser-like surfaces.

YOUR_APP_NAME — Unique application identifier across platforms (e.g. "VideoApp Taro", "VideoApp WebView").

YOUR_CUSTOMER_KEY — Conviva account identifier. Find it in Pulse under My Profile.

appVersion — Application version string.

convivaAppTracker(configuration) — init parameters

Call exactly once at app boot.

| Param | Required | Type | Default | Notes | |-------|----------|------|---------|-------| | convivaCustomerKey | ✅ | string | — | Provided by Conviva | | appId | ✅ | string | — | Unique application identifier | | appVersion | optional | string | — | Application version | | httpTransport | optional | HttpTransport | browser XMLHttpRequest fallback | Required in non-browser runtimes | | storage | optional | StorageAdapter | browser localStorage fallback | Required in non-browser runtimes | | timers | optional | TimerAdapter | global timer fns fallback | Required if global timers unavailable | | deviceMetadata | optional | ConvivaDeviceMetadata | — | Device brand / model / OS info — see Set device metadata in More Features | | bufferSize | optional | number | 1 | Max events buffered before send | | proxyGatewayUrl / gatewayUrl | optional | string | — | Proxy / gateway URL overrides |

Calling APIs before initialization

API calls made before convivaAppTracker() is initialized are automatically queued and replayed once the tracker is ready. You can instrument your app without waiting for the tracker to bootstrap.


Supported Platforms & Adapter Packages

| Platform | Companion adapter package | Loaded via | |----------|---------------------------|------------| | Taro mini-program (WeChat, Alipay, ByteDance, etc.) | @convivainc/conviva-js-custom-app-analytics-sdk-taro-adapters | NPM | | Amazon Kepler / VegaOS React Native | @convivainc/conviva-js-custom-app-analytics-sdk-vegaos-adapters | NPM | | WebView / browser surfaces | None — built-in browser fallbacks used automatically | NPM or script tag | | Other React Native runtimes | Use VegaOS adapters or implement your own (see Implement your own adapter in More Features) | NPM |


More Features

deviceMetadata is an object containing key-value pairs for predefined values, such as DeviceType and DeviceCategory, as well as additional properties like DeviceBrand, DeviceManufacturer, and DeviceModel.

In non-browser runtimes (Taro mini-programs, Amazon Kepler / VegaOS, embedded JS) the SDK cannot infer the device automatically — you must set deviceMetadata manually at init time. The same applies to set-top boxes, smart TVs, gaming consoles, and similar environments.

Example:

import {
  convivaAppTracker,
  ConvivaDeviceMetadata,
} from '@convivainc/conviva-js-custom-app-analytics-sdk';

const deviceMetadata: ConvivaDeviceMetadata = {
  DeviceBrand: 'Samsung',
  DeviceManufacturer: 'Samsung',
  DeviceModel: 'UTU7000',
  DeviceType: 'SmartTV',
  OperatingSystemName: 'Tizen',
  OperatingSystemVersion: '8.0',
  DeviceCategory: 'SAMSUNGTV',
  FrameworkName: 'React TV',
  FrameworkVersion: '1.0.0',
};

convivaAppTracker({
  convivaCustomerKey: 'YOUR_CUSTOMER_KEY',
  appId: 'YOUR_APP_NAME',
  appVersion: '1.0.0',
  ...adapters,
  deviceMetadata,
});

Predefined metadata keys:

| Key | Type | Description | Example values | |-----|------|-------------|----------------| | DeviceBrand | string | Brand of the device | "Comcast", "LG", "Google", "Vizio" | | DeviceManufacturer | string | Manufacturer of the device | "Sony", "Comcast", "Google", "Microsoft" | | DeviceModel | string | Model of the device | "Comcast Flex", "UTU7000_KA", "Xbox One" | | DeviceType | Prescribed DeviceType value | Type of the device — must be one of the prescribed values (table below). Invalid values are omitted from the payload. | DESKTOP, Console, SmartTV | | DeviceVersion | string | Device firmware version | "10", "9" | | OperatingSystemName | string | OS name (uppercase preferred) | "Tizen", "webOS", "Linux", "Xbox OS", "Chrome OS" | | OperatingSystemVersion | string | OS version | "10.10.1", "8.1", "T-INFOLINK2012-1012" | | DeviceCategory | Prescribed DeviceCategory value | Device category — must be one of the prescribed values (table below). Invalid values are reported as "INVALID: <value>" in the payload. | SAMSUNGTV, LGTV, VIDAA, WEB | | FrameworkName | string | Application framework name | "React TV", "LightningJS", "Angular", "Taro" | | FrameworkVersion | string | Application framework version | "1.2.3" |

For DeviceCategory, use only the prescribed values listed below. If an invalid value is provided, the sensor reports it as INVALID: <value> — e.g. setting DeviceCategory: 'TV' results in "INVALID: TV" in the payload. Use VIDAA for Hisense Vidaa TVs, SAMSUNGTV for Samsung TVs, LGTV for LG TVs, etc.

For DeviceType, use only the prescribed values listed below. Invalid values are silently omitted and dvt is not set in the payload.

DeviceCategory — pre-defined string values

| Value | Description | |-------|-------------| | AND | Android device — Samsung Galaxy, Amazon Fire TV, Android TV, Android Tablet, etc. | | APL | Apple device — iPhone, Apple TV, etc. | | CHR | Google Chromecast STB or Android TV with built-in Chromecast | | DSKAPP | Desktop / notebook computer where video is played in an installed app (not browser) | | SIMULATOR | Simulated video session used for testing | | KAIOS | KaiOS-based phone or device (e.g. Lyf Jio F30C) | | LGTV | LG smart TV — NetCast or webOS | | LNX | Set-top boxes and smart TVs using custom Linux-based SDKs | | NINTENDO | Nintendo console — Wii, Switch | | PS | PlayStation console — PS3, PS4 | | RK | Roku device | | SAMSUNGTV | Samsung smart TV — Orsay or Tizen | | VIDAA | Hisense Vidaa-based devices | | VIZIOTV | Native app on Vizio TV (SmartCast platform, 2016+) | | WEB | Any in-browser HTML5 player — Chrome, Edge, Firefox, Safari, etc. | | WIN | Windows OS handheld — Windows Phone, Windows Tablet | | XB | Xbox console — Xbox 360, Xbox One |

DeviceType — pre-defined string values

| Value | Description | |-------|-------------| | DESKTOP | Desktop or laptop computer | | Console | Gaming console | | Settop | Set-top box | | Mobile | Mobile phone | | Tablet | Tablet | | SmartTV | Smart TV | | Vehicle | Vehicle infotainment system | | Other | Other device types |

| Param | Required | Type | Notes | |-------|----------|------|-------| | title | ✅ | string | Page/screen title — there is no document.title fallback in custom-tracker | | url | optional | string | Defaults to ''. Use a meaningful path (e.g. '/cart') for non-DOM runtimes | | contextCallback | optional | () => Array<SelfDescribingJson> | Per-event additional contexts | | context | optional | Array<SelfDescribingJson> | One-shot extra contexts | | timestamp | optional | number | Event timestamp override (ms epoch) |

trackPageView({ title: 'Cart', url: '/cart' });

Script-tag: convivaCustomTracking.trackPageView({ title: 'Cart', url: '/cart' });

| Param | Required | Type | Notes | |-------|----------|------|-------| | name | ✅ | string | Non-empty; SDK rejects empty/whitespace-only names | | data | ✅ | any | Any value; non-string values are JSON-stringified | | context / timestamp | optional | as above | |

trackCustomEvent({
  name: 'sign_up_completed',
  data: { plan: 'premium', source: 'landing-page' },
});

Script-tag: convivaCustomTracking.trackCustomEvent({ name: '...', data: {...} });

| Param | Required | Type | Notes | |-------|----------|------|-------| | requestDetails | ✅ | RequestDetails | object — see fields below | | responseDetails | ✅ | ResponseDetails | object — see fields below |

RequestDetails (all sub-fields optional):

| Field | Type | Notes | |-------|------|-------| | method | string | HTTP verb ('GET', 'POST', …) | | url | string | Full request URL (used as the conditional-collection match target) | | headers | Record<string, string> | Request headers | | body | any | Request body | | requestTimestamp | number | Epoch ms (e.g. Date.now()); paired with responseTimestamp to compute duration and evaluate the conditional-collection dur rule | | size | number | Request payload size in bytes | | traceparent | string | W3C Trace Context traceparent header value (forwarded as-is) |

ResponseDetails (all sub-fields optional):

| Field | Type | Notes | |-------|------|-------| | status | number | HTTP status code (e.g. 200, 404) | | statusText | string | HTTP status text (e.g. 'OK') | | url | string | Final response URL after any redirects | | headers | Record<string, string> | Response headers | | body | any | Response body | | event | string | SSE / streaming event name when the response is an event stream | | size | number | Response payload size in bytes | | responseTimestamp | number | Epoch ms (e.g. Date.now()); paired with requestTimestamp to compute duration and evaluate the conditional-collection dur rule |

Pass requestTimestamp + responseTimestamp so the SDK can compute duration and evaluate conditional-collection dur rules. The two timestamp fields are consumed internally and replaced by duration in the emitted event payload.

const t0 = Date.now();
const res = await fetch(url);
const body = await res.text();
const t1 = Date.now();
trackNetworkRequest({
  requestDetails: { url, method: 'GET', requestTimestamp: t0 },
  responseDetails: { status: res.status, statusText: res.statusText, responseTimestamp: t1, body },
});

Script-tag: convivaCustomTracking.trackNetworkRequest({...});

Canonical click entry point. Honors remote-config fields clickcc.en (master gate), clickcc.collect, clickcc.block, and clickcc.collectattr (allow-list for extra keys).

Core click fields (these are the canonical set the SDK forwards to Conviva; any other key is dropped unless listed in the clickcc.collectattr allow-list):

| Field | Required | Type | Notes / example | |-------|----------|------|-----------------| | elementName | ✅ | string | Tag name of the clicked element — e.g. 'button', 'a' (link), 'div', 'input', 'img'. In non-DOM runtimes pass the equivalent component / element type your framework uses. | | elementType | ✅ | string | The element's type attribute (or equivalent role). For <input> elements this is the input type — e.g. 'text', 'password', 'checkbox', 'radio', 'submit', 'button', 'file'. For other elements this is whatever role / type your UI framework exposes. | | xpath | optional but strongly recommended | string | Stable element locator; downstream analytics rely on it for click-path attribution. | | id | optional | string | Element id attribute | | class | optional | string | Space-separated class names on the element | | name | optional | string | Element name attribute (form fields) | | text | optional | string | Inner text / label shown on the element | | placeholder | optional | string | Placeholder attribute (input/textarea) | | value | optional | string | Element value attribute | | checked | optional | 'true' \| 'false' | Checked state for <input type="checkbox"> / radio at click time | | targetUrl | optional | string | Target URL for <a> (href) or form action | | target | optional | string | target attribute (e.g. '_blank') | | xlink:href | optional | string | SVG <use> reference | | Custom keys (e.g. data-product-id) | optional | string | Only emitted when listed in the clickcc.collectattr remote-config allow-list |

trackClick({
  elementName: 'button',
  elementType: 'submit',
  id: 'submit-btn',
  text: 'Submit',
  xpath: '/html/body/div[1]/form/button',
});

Script-tag: convivaCustomTracking.trackClick({...});

| Param | Required | Type | Notes | |-------|----------|------|-------| | totalOrderAmount | ✅ | number | | | transactionId | ✅ | string | | | currency | ✅ | string | ISO 4217 ('USD', 'EUR', etc.) | | taxAmount, shippingCost, discount, cartSize | optional | number | | | paymentMethod, paymentProvider, orderStatus | optional | string | | | items | optional | RevenueEventItem[] | Per-item details | | extraMetadata | optional | Record<string, unknown> | |

RevenueEventItem (all optional): productId, name, sku, category, unitPrice, quantity, discount, brand, variant, extraMetadata.

trackRevenueEvent({
  totalOrderAmount: 99.99,
  transactionId: 'order-12345',
  currency: 'USD',
  items: [{ productId: 'sku-1', quantity: 2, unitPrice: 49.99 }],
});

Script-tag: convivaCustomTracking.trackRevenueEvent({...});

| Param | Required | Type | Notes | |-------|----------|------|-------| | message | ✅ | string | Truncated to 2048 chars | | filename, lineno, colno | optional | string / number | Source location | | error | optional | Error | Stack trace truncated to 8192 chars |

try { riskyOp(); } catch (err) {
  trackError({ message: err.message, error: err });
}

Script-tag: convivaCustomTracking.trackError({...});

| Param | Required | Type | Notes | |-------|----------|------|-------| | backgroundIndex / foregroundIndex | ✅ | number | Monotonically increasing counter for the session |

trackAppBackground({ backgroundIndex: 1 });
trackAppForeground({ foregroundIndex: 1 });

Script-tag: convivaCustomTracking.trackAppBackground({ backgroundIndex: 1 });

Forwards a Conviva video analytics event payload. The event object shape is defined by the Conviva video analytics pipeline; pass through unchanged.

trackVideoEvent(videoEventPayload);

| Param | Required | Type | Notes | |-------|----------|------|-------| | userId | ✅ | string \| null \| undefined | Pass null / undefined to clear. Do NOT pass PII (emails, phone numbers, real names) |

setUserId('user-123');
setUserId(null);  // clear

| Param | Required | Type | Notes | |-------|----------|------|-------| | tags (set) | ✅ | Record<string, string> | Session-level key/value tags | | keys (unset) | ✅ | string[] | Keys to remove |

setCustomTags({ subscriptionTier: 'premium', region: 'us-west' });
unsetCustomTags(['region']);

If your target runtime isn't covered by an existing adapter package, implement the three adapter interfaces directly and pass them as top-level fields on the config: httpTransport, storage, timers. The existing createTaroAdapters / createVegaOSAdapters factories simply return an object with those three keys, which is why ...adapters works in the usage examples above.

All three interface types are exported from @convivainc/conviva-js-custom-app-analytics-sdk:

import type {
  HttpTransport,
  HttpResponse,
  StorageAdapter,
  TimerAdapter,
} from '@convivainc/conviva-js-custom-app-analytics-sdk';

Interface contracts:

// HTTP — single method, covers both POST (event delivery) and GET (remote config fetch).
// Must NEVER throw. Return a fulfilled Promise even on network failure
// (use status: 0 for transport errors so the SDK can treat it as failure without crashing).
interface HttpTransport {
  sendRequest(
    url: string,
    method: 'GET' | 'POST',
    options?: {
      payload?: Uint8Array | string;
      contentType?: string;
      headers?: Record<string, string>;
      timeout?: number;
    }
  ): Promise<HttpResponse>;
}

interface HttpResponse {
  status: number;                          // HTTP status (or 0 on transport error)
  body?: string;                           // Response body as string (RC fetch reads JSON from here)
  headers?: Record<string, string>;        // Lowercased header names; SDK reads `rcv` from CTP responses
}

// Storage — SYNCHRONOUS key-value persistence.
// Used for: client ID, remote config cache, event queue, sampling random number.
// If your platform's storage is async, pre-hydrate keys at boot
// (see the VegaOS adapter's `createVegaOSAdapters` for the canonical pattern).
interface StorageAdapter {
  getItem(key: string): string | null;
  setItem(key: string, value: string): void;
  removeItem(key: string): void;
}

// Timers — same shape as the standard timer functions in any JS runtime.
// IDs can be any opaque value (number, object, symbol); the SDK only uses them with clear*.
interface TimerAdapter {
  setTimeout(fn: () => void, delay: number): unknown;
  setInterval(fn: () => void, interval: number): unknown;
  clearTimeout(id: unknown): void;
  clearInterval(id: unknown): void;
}

Stub implementation example:

import {
  convivaAppTracker,
  type HttpTransport,
  type StorageAdapter,
  type TimerAdapter,
} from '@convivainc/conviva-js-custom-app-analytics-sdk';

const myTransport: HttpTransport = {
  async sendRequest(url, method, options) {
    try {
      const res = await myFetch(url, { method, body: options?.payload, headers: options?.headers });
      const body = await res.text();
      const headers: Record<string, string> = {};
      res.headers.forEach((v: string, k: string) => { headers[k.toLowerCase()] = v; });
      return { status: res.status, body, headers };
    } catch {
      return { status: 0, body: '', headers: {} };  // never throw
    }
  },
};

const myStorage: StorageAdapter = {
  getItem: (k) => mySyncStore.get(k) ?? null,
  setItem: (k, v) => mySyncStore.set(k, v),
  removeItem: (k) => mySyncStore.delete(k),
};

const myTimers: TimerAdapter = {
  setTimeout:    (fn, ms) => setTimeout(fn, ms),
  setInterval:   (fn, ms) => setInterval(fn, ms),
  clearTimeout:  (id)     => clearTimeout(id as number),
  clearInterval: (id)     => clearInterval(id as number),
};

convivaAppTracker({
  convivaCustomerKey: 'YOUR_CUSTOMER_KEY',
  appId: 'YOUR_APP_NAME',
  appVersion: '1.0.0',
  httpTransport: myTransport,
  storage:       myStorage,
  timers:        myTimers,
});

Async storage note. The StorageAdapter contract is synchronous because the SDK reads identity / sampling values during the synchronous init path. If your platform only provides an async storage API (e.g. React Native AsyncStorage, Kepler AsyncStorage), pre-hydrate the Conviva-owned keys (Conviva* prefix and convivaOutQueue_* prefix) into an in-memory map at app boot, then wrap that map in a synchronous StorageAdapter. The VegaOS adapter package does exactly this — see its createVegaOSAdapters() factory for reference.

Terminal teardown: stops heartbeat, performs one final emitter flush, marks the tracker closed, and unregisters it from the global registry.

import { cleanup } from '@convivainc/conviva-js-custom-app-analytics-sdk';

cleanup();

After cleanup(), the tracker handle is no longer usable — subsequent API calls become silent no-ops. Call once at app shutdown if your runtime needs explicit teardown.

Single-arg or no-arg helpers for identity, URL/title overrides, and emitter buffer control:

| API | Signature | Purpose | |-----|-----------|---------| | getClientId() | (trackers?) => string | Read the Conviva client ID | | setClientId(clientId) | (string, trackers?) => void | Set a custom client ID (special-case use only) | | setCustomUrl(url) | (string, trackers?) => void | Override URL on subsequent events | | setDocumentTitle(title) | (string, trackers?) => void | Override page title | | setReferrerUrl(url) | (string, trackers?) => void | Override referrer | | flushBuffer(config?) | (FlushBufferConfiguration?, trackers?) => void | Force immediate emitter flush; optional newBufferSize | | setBufferSize(size) | (number, trackers?) => void | Change emitter buffer size | | setCollectorUrl(url) | (string, trackers?) => void | Change collector URL at runtime |

All track* APIs accept an optional final trackers?: string[] argument (list of tracker namespaces to dispatch to — omit to dispatch to all registered trackers). All event objects also accept CommonEventProperties (context?: Array<SelfDescribingJson>, timestamp?: number | TrueTimestamp | DeviceTimestamp).


FAQ

Why are adapters separate packages?

The SDK targets multiple runtimes with different platform APIs. Bundling all platforms into one package would force every customer to ship code for runtimes they don't use. Separate adapter packages keep your bundle lean.

Does the SDK ever throw to the host app?

No. Every public API and adapter method is wrapped in try/catch with safe defaults. SDK failures degrade silently — they never crash the host app.

How is this different from @convivainc/conviva-js-appanalytics?

conviva-js-appanalytics targets browser environments (DOM, window, browser cookies). This SDK targets non-browser JavaScript runtimes (mini-programs, RN, embedded JS, WebView surfaces) where browser APIs may not be available or where you need explicit platform adapters.

Can I use this in a regular browser web app?

Yes — the script-tag UMD bundle works in browsers and uses browser-fallback adapters automatically. But for a pure-browser web app, prefer @convivainc/conviva-js-appanalytics — it's purpose-built for that environment.

Where is the changelog?

See CHANGELOG.md.