@webority/analytics 0.36.1 → 0.38.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/dist/check-events.js +14 -14
  2. package/dist/chunk-LGUY6CCC.js +1 -0
  3. package/dist/chunk-UMKCGH25.js +1 -0
  4. package/dist/errors.js +1 -1
  5. package/dist/generate-events.js +12 -12
  6. package/dist/index.js +1 -1
  7. package/dist/node.js +1 -1
  8. package/dist/react-native.js +1 -1
  9. package/dist/site.js +1 -1
  10. package/dist/types/after-interaction.d.ts +6 -0
  11. package/dist/types/analytics.d.ts +49 -0
  12. package/dist/types/attribution.d.ts +34 -0
  13. package/dist/types/catalogue/check-events.d.ts +2 -0
  14. package/dist/types/catalogue/check.d.ts +32 -0
  15. package/dist/types/catalogue/generate-events.d.ts +2 -0
  16. package/dist/types/catalogue/generate.d.ts +28 -0
  17. package/dist/types/catalogue/plan.d.ts +97 -0
  18. package/dist/types/catalogue/scan.d.ts +42 -0
  19. package/dist/types/channels.d.ts +24 -0
  20. package/dist/types/consent-regions.d.ts +2 -0
  21. package/dist/types/consent.d.ts +83 -0
  22. package/dist/types/errors.d.ts +35 -0
  23. package/dist/types/event-registry.d.ts +19 -0
  24. package/dist/types/feature-flags.d.ts +26 -0
  25. package/dist/types/index.d.ts +5 -0
  26. package/dist/types/node/errors.d.ts +38 -0
  27. package/dist/types/node/index.d.ts +1 -0
  28. package/dist/types/posthog-bridge.d.ts +22 -0
  29. package/dist/types/react-native/index.d.ts +90 -0
  30. package/dist/types/react-native/native-modules.d.ts +41 -0
  31. package/dist/types/site-events.d.ts +16 -0
  32. package/dist/types/site-posthog-snippet.d.ts +27 -0
  33. package/dist/types/site-posthog.d.ts +62 -0
  34. package/dist/types/site-web-vitals-script.d.ts +13 -0
  35. package/dist/types/site-web-vitals.d.ts +4 -0
  36. package/dist/types/site.d.ts +8 -0
  37. package/dist/types/state.d.ts +43 -0
  38. package/dist/types/tags.d.ts +35 -0
  39. package/dist/types/tours.d.ts +8 -0
  40. package/dist/types/track-helpers.d.ts +8 -0
  41. package/dist/types/url-scrub.d.ts +14 -0
  42. package/dist/types/vocabulary.d.ts +76 -0
  43. package/dist/types/web-vitals-global.d.ts +1 -0
  44. package/dist/types/web-vitals.d.ts +71 -0
  45. package/dist/{web-vitals-RMISAXOY.js → web-vitals-DND62YT4.js} +1 -1
  46. package/dist/webority-analytics-site.global.js +1 -1
  47. package/dist/webority-analytics-web-vitals.global.js +1 -1
  48. package/package.json +31 -12
  49. package/dist/chunk-BXYJOYLR.js +0 -1
  50. package/dist/chunk-TPTUIQE4.js +0 -1
@@ -0,0 +1,32 @@
1
+ import type { MergedPlan } from "./plan.ts";
2
+ export type SourceProblem = {
3
+ file: string | null;
4
+ line: number | null;
5
+ message: string;
6
+ };
7
+ export type CheckSummary = {
8
+ constants: number;
9
+ callSites: number;
10
+ files: number;
11
+ };
12
+ export declare function fleetConstantsOf(plan: MergedPlan): Map<string, string>;
13
+ /**
14
+ * Checks a product's source against its merged plan. For each source in the plan:
15
+ * - every event constant in its constant files must be an event in the plan;
16
+ * - every use of those constants in the scanned folders must name a known constant, the plan must
17
+ * list the source's sender for that event, and each property written inline must be declared on
18
+ * the event or as a common property;
19
+ * - every event name written in a call of the source's `calls` (and, in JavaScript, of
20
+ * trackSiteEvent) must be in the plan, held to the same sender and property rules.
21
+ * Returns { problems: [{ file, line, message }], summary }.
22
+ */
23
+ export declare function checkSources(plan: MergedPlan, root: string): {
24
+ problems: SourceProblem[];
25
+ summary: CheckSummary;
26
+ };
27
+ /**
28
+ * The folder a plan's source paths are relative to: the repo root when the plan sits in `.webority/`,
29
+ * otherwise the plan's own folder.
30
+ */
31
+ export declare function defaultRootOf(planFile: string): string;
32
+ export declare function toPascalCase(name: string): string;
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
@@ -0,0 +1,28 @@
1
+ import type { CatalogueEvent, MergedPlan } from "./plan.ts";
2
+ /**
3
+ * The events a generated file carries, in plan order: fleet events first, then the product's own.
4
+ * sender limits them to one sender's events; productOnly drops the ones the base plan defines.
5
+ */
6
+ export declare function selectEvents(plan: MergedPlan, { sender, productOnly }?: {
7
+ sender?: string | null;
8
+ productOnly?: boolean;
9
+ }): CatalogueEvent[];
10
+ /**
11
+ * A JavaScript module exporting one frozen object of event names. keys "constant" gives
12
+ * SIGNUP_STARTED (the package's own `events` style), "pascal" gives SignupStarted.
13
+ */
14
+ export declare function renderJavaScript(events: CatalogueEvent[], { exportName, keys, planLabel, }?: {
15
+ exportName?: string;
16
+ keys?: "constant" | "pascal";
17
+ planLabel?: string;
18
+ }): string;
19
+ /**
20
+ * A C# file holding one static class of event-name constants, file-scoped namespace, marked
21
+ * auto-generated so analyzers leave it alone.
22
+ */
23
+ export declare function renderCSharp(events: CatalogueEvent[], { namespace, className, accessibility, planLabel, }: {
24
+ namespace: string;
25
+ className: string;
26
+ accessibility?: "public" | "internal";
27
+ planLabel?: string;
28
+ }): string;
@@ -0,0 +1,97 @@
1
+ export declare const FLEET_PLAN_ID = "@webority/analytics/fleet";
2
+ export declare const FUNNEL_STAGES: readonly ["acquisition", "activation", "engagement", "retention", "revenue", "referral", "support", "quality"];
3
+ export type FunnelStage = (typeof FUNNEL_STAGES)[number];
4
+ export declare const PERSONAL_DATA_CLASSES: readonly ["none", "pseudonymous", "personal"];
5
+ export type PersonalDataClass = (typeof PERSONAL_DATA_CLASSES)[number];
6
+ export declare const PROPERTY_TYPES: readonly ["string", "integer", "number", "boolean", "array", "object"];
7
+ export type PropertyType = (typeof PROPERTY_TYPES)[number];
8
+ export declare const PROPERTY_NAME_PATTERN: RegExp;
9
+ declare const LANGUAGES: readonly ["csharp", "javascript"];
10
+ export type SourceLanguage = (typeof LANGUAGES)[number];
11
+ export type PropertyDefinition = {
12
+ type: PropertyType;
13
+ description?: string;
14
+ values?: unknown[];
15
+ nullable?: boolean;
16
+ personalData?: PersonalDataClass;
17
+ };
18
+ export type EventDefinition = {
19
+ description?: string;
20
+ stage?: FunnelStage;
21
+ owner?: string;
22
+ personalData?: PersonalDataClass;
23
+ senders?: string[];
24
+ properties?: Record<string, PropertyDefinition>;
25
+ };
26
+ export type SourceDefinition = {
27
+ sender: string;
28
+ language: SourceLanguage;
29
+ constants?: string[];
30
+ references?: string[];
31
+ calls?: string[];
32
+ ignoreConstants?: string[];
33
+ scan?: string[];
34
+ exclude?: string[];
35
+ };
36
+ export type TrackingPlan = {
37
+ $schema?: string;
38
+ product: string;
39
+ extends?: string;
40
+ description?: string;
41
+ commonProperties?: Record<string, PropertyDefinition>;
42
+ events: Record<string, EventDefinition>;
43
+ sources?: SourceDefinition[];
44
+ };
45
+ export type CatalogueEvent = {
46
+ name: string;
47
+ description: string | undefined;
48
+ stage: FunnelStage | undefined;
49
+ owner: string | undefined;
50
+ personalData: PersonalDataClass | undefined;
51
+ senders: string[];
52
+ properties: Map<string, PropertyDefinition>;
53
+ origin: string;
54
+ };
55
+ export type CommonProperty = PropertyDefinition & {
56
+ origin: string;
57
+ };
58
+ export type MergedPlan = {
59
+ product: string;
60
+ events: Map<string, CatalogueEvent>;
61
+ commonProperties: Map<string, CommonProperty>;
62
+ sources: SourceDefinition[];
63
+ file: string;
64
+ };
65
+ export type PlanLoad = {
66
+ plan: MergedPlan | null;
67
+ problems: string[];
68
+ };
69
+ /**
70
+ * Reads a tracking plan and everything it extends, merged into one catalogue. Never throws on a bad
71
+ * plan: every problem is returned, so a check can list them all at once.
72
+ * Returns { plan, problems } where plan is { product, events: Map, commonProperties: Map, sources, file }.
73
+ */
74
+ export declare function loadPlan(file: string): PlanLoad;
75
+ export declare function loadFleetPlan(): PlanLoad;
76
+ /**
77
+ * Merges a plan's own declarations over its base. A product may list a base event again only to add
78
+ * properties or senders; anything else on it, or a property redeclared with another type, is a problem.
79
+ */
80
+ export declare function mergePlan(base: MergedPlan | null, raw: TrackingPlan, label?: string): {
81
+ plan: MergedPlan;
82
+ problems: string[];
83
+ };
84
+ /**
85
+ * The structural rules of tracking-plan.schema.json, checked without a schema library so the check
86
+ * has no runtime dependency. The schema is what an editor validates against; this is what the build
87
+ * enforces, and the catalogue test keeps their enums the same.
88
+ */
89
+ export declare function validatePlanShape(raw: unknown, label?: string): string[];
90
+ /**
91
+ * Checks one event as it would be sent: a name the catalogue does not hold, a property declared
92
+ * neither on the event nor as a common property, or a value of the wrong type. PostHog's own `$`
93
+ * events and properties are not the product's vocabulary and are skipped.
94
+ * Returns a list of problem strings, empty when the event is valid.
95
+ */
96
+ export declare function validateEvent(plan: MergedPlan, name: unknown, properties?: unknown): string[];
97
+ export {};
@@ -0,0 +1,42 @@
1
+ import type { SourceLanguage } from "./plan.ts";
2
+ export type ConstantEntry = {
3
+ name: string;
4
+ value: string | null;
5
+ line: number;
6
+ };
7
+ export type EventReference = {
8
+ constant: string;
9
+ line: number;
10
+ properties: string[] | null;
11
+ };
12
+ export type EventCall = {
13
+ call: string;
14
+ name: string;
15
+ line: number;
16
+ properties: string[] | null;
17
+ };
18
+ /**
19
+ * Event constants declared in a C# file: `const string Name = "value";`, or `= AnalyticsEvents.X;`
20
+ * resolved through fleetConstants (PascalCase name to event name). Nested classes are flattened to
21
+ * the constant's own name. Returns [{ name, value, line }]; value is null for a reference that
22
+ * cannot be resolved.
23
+ */
24
+ export declare function readCSharpConstants(text: string, fleetConstants?: ReadonlyMap<string, string>): ConstantEntry[];
25
+ /**
26
+ * Event constants declared in a JavaScript file as string values of object literals,
27
+ * `Key: "value"` or `KEY: 'value'`. Returns [{ name, value, line }].
28
+ */
29
+ export declare function readJavaScriptConstants(text: string): ConstantEntry[];
30
+ /**
31
+ * Every use of `<reference>.<Constant>` (or `<reference>.<Nested>.<Constant>`) in a source file, with
32
+ * the property names written inline beside it. Returns [{ constant, line, properties }], where
33
+ * properties is an array of names, or null when no inline properties were found.
34
+ */
35
+ export declare function findEventReferences(text: string, references: readonly string[], language: SourceLanguage): EventReference[];
36
+ /**
37
+ * Every call of one of the named functions (`trackSiteEvent("x", ...)`, `window.lumexTrack("x", ...)`)
38
+ * whose first argument writes its event name, with the property names written inline beside it.
39
+ * Returns [{ call, name, line, properties }], one entry per name, so both arms of a ternary count.
40
+ */
41
+ export declare function findEventCalls(text: string, calls: readonly string[], language: SourceLanguage): EventCall[];
42
+ export declare function maskComments(text: string, language: SourceLanguage): string;
@@ -0,0 +1,24 @@
1
+ import type { AttributionTouch } from "./attribution.ts";
2
+ declare const AI_ASSISTANTS: readonly [readonly ["chatgpt", readonly ["chatgpt.com", "chat.openai.com"]], readonly ["perplexity", readonly ["perplexity.ai"]], readonly ["gemini", readonly ["gemini.google.com"]], readonly ["copilot", readonly ["copilot.microsoft.com"]], readonly ["claude", readonly ["claude.ai"]], readonly ["you", readonly ["you.com"]], readonly ["phind", readonly ["phind.com"]], readonly ["deepseek", readonly ["deepseek.com"]], readonly ["grok", readonly ["grok.com"]], readonly ["meta_ai", readonly ["meta.ai"]], readonly ["poe", readonly ["poe.com"]]];
3
+ type AiAssistant = (typeof AI_ASSISTANTS)[number][0];
4
+ export declare const channels: Readonly<{
5
+ readonly DIRECT: "direct";
6
+ readonly GOOGLE: "google";
7
+ readonly META: "meta";
8
+ readonly LINKEDIN: "linkedin";
9
+ readonly MICROSOFT: "microsoft";
10
+ readonly OTHER: "other";
11
+ readonly AI_ASSISTANT: "ai_assistant";
12
+ readonly ORGANIC_SEARCH: "organic_search";
13
+ readonly ORGANIC_SOCIAL: "organic_social";
14
+ readonly REFERRAL: "referral";
15
+ }>;
16
+ type Channel = (typeof channels)[keyof typeof channels];
17
+ /**
18
+ * The channel of a touch, as captureAttribution stores it. utm_source wins, then click ids; an
19
+ * untagged visit is classified by its referrer's host.
20
+ */
21
+ export declare function resolveChannel(touch: Partial<AttributionTouch> | null | undefined): Channel;
22
+ /** The AI assistant ("chatgpt", "perplexity", "gemini", "copilot", "claude"...) behind a touch, or "". */
23
+ export declare function resolveAiSource(touch: Partial<AttributionTouch> | null | undefined): AiAssistant | "";
24
+ export {};
@@ -0,0 +1,2 @@
1
+ export declare const OPT_IN_COUNTRIES: readonly ["AT", "BE", "BG", "HR", "CY", "CZ", "DK", "EE", "FI", "FR", "DE", "GR", "HU", "IE", "IT", "LV", "LT", "LU", "MT", "NL", "PL", "PT", "RO", "SK", "SI", "ES", "SE", "IS", "LI", "NO", "GB", "CH"];
2
+ export declare function requiresOptIn(countryCode: string | null | undefined): boolean;
@@ -0,0 +1,83 @@
1
+ export declare const CONSENT_COOKIE_NAME = "webority_cookie_consent";
2
+ export declare const CONSENT_CHANGE_EVENT = "webority-consent-change";
3
+ declare global {
4
+ interface Window {
5
+ dataLayer?: unknown[];
6
+ }
7
+ }
8
+ /** The categories a visitor chooses between. Essential cookies are always on, so they are not a choice. */
9
+ export type ConsentCategory = "analytics" | "functional" | "marketing";
10
+ /**
11
+ * The saved choice, shaped as the webority_cookie_consent cookie holds it. timestamp is an ISO
12
+ * string when this package wrote the cookie. A cookie edited by hand can hold any JSON value there,
13
+ * so it stays unknown and is only read after a type check.
14
+ */
15
+ export type ConsentState = Record<ConsentCategory, boolean> & {
16
+ essential: true;
17
+ timestamp: unknown;
18
+ };
19
+ type SharedConsentOptions = {
20
+ cookieDomain?: string;
21
+ cookieDays?: number;
22
+ adStorage?: boolean;
23
+ regionCookie?: string;
24
+ };
25
+ /**
26
+ * The initConsent options. requiresOptIn comes from the host's country lookup and is required, except
27
+ * under strictOptIn, which asks every region and so may leave it out. requiresOptIn: false beside
28
+ * strictOptIn throws at run time, and the type rules it out too.
29
+ */
30
+ export type ConsentOptions = SharedConsentOptions & ({
31
+ requiresOptIn: boolean;
32
+ strictOptIn?: false | undefined;
33
+ } | {
34
+ requiresOptIn?: true | undefined;
35
+ strictOptIn: true;
36
+ });
37
+ type Region = "eea" | "other";
38
+ type ConsentView = Omit<ConsentState, "timestamp"> & {
39
+ decided: boolean;
40
+ };
41
+ type ConsentListener = (consent: ConsentView) => void;
42
+ /**
43
+ * Sets Google Consent Mode's defaults and applies the visitor's saved choice. Call once, first,
44
+ * before initAnalytics, loadTags or captureAttribution. requiresOptIn comes from the host, which
45
+ * knows the visitor's country (requiresOptIn(countryCode)); guessing it in the browser misplaces
46
+ * VPN users. cookieDomain (".capnix.ai") shares one choice between the website and every portal
47
+ * subdomain; without it the choice stays on the current host.
48
+ *
49
+ * strictOptIn asks every visitor in every region: Consent Mode is denied everywhere until they
50
+ * choose, loadTags holds Tag Manager and Ahrefs until consent, and requiresOptIn may be left out.
51
+ * adStorage says whether marketing consent also grants Google's ad_* signals: true by default,
52
+ * false under strictOptIn. cookieDays is the saved choice's lifetime, 365 by default.
53
+ *
54
+ * regionCookie names a cookie the host sets to "eea" or "other" (see setConsentRegion), read
55
+ * once, synchronously, here. With no saved choice, "other" lifts the opt-in default: analytics and
56
+ * functional start on, marketing stays off until chosen, and Google's ad signals follow adStorage.
57
+ * "eea", a missing cookie or any other value keeps the opt-in default. strictOptIn ignores it, and
58
+ * a saved choice always wins.
59
+ */
60
+ export declare function initConsent(options: ConsentOptions): void;
61
+ /**
62
+ * Applies the visitor's region when the host learns it after initConsent (a country check that
63
+ * answered later than the page). "other" lifts the opt-in default and "eea" restores it, with the
64
+ * same rule initConsent's regionCookie applies. onConsentChange listeners fire when the effective
65
+ * consent changes; a saved choice is untouched and nothing fires.
66
+ */
67
+ export declare function setConsentRegion(region: Region): void;
68
+ export declare function isConsentInitialized(): boolean;
69
+ export declare function isStrictOptIn(): boolean;
70
+ export declare function isAdStorageEnabled(): boolean;
71
+ /**
72
+ * The visitor's current consent. Before they choose (decided: false) every optional category
73
+ * follows the region default: denied where opt-in is required, granted everywhere else. A region
74
+ * of "other" (regionCookie, setConsentRegion) grants analytics and functional where opt-in would
75
+ * otherwise be required; marketing stays off until the visitor chooses it.
76
+ */
77
+ export declare function getConsent(): ConsentView;
78
+ /** Records the visitor's choice, tells Google, and notifies every listener. */
79
+ export declare function saveConsent(preferences?: Partial<Record<ConsentCategory, boolean>>): void;
80
+ /** Calls listener with the new consent after every saveConsent. Returns an unsubscribe function. */
81
+ export declare function onConsentChange(listener: ConsentListener): () => boolean;
82
+ export declare function resetConsentForTests(): void;
83
+ export {};
@@ -0,0 +1,35 @@
1
+ import type { PostHog } from "posthog-js";
2
+ type ErrorState = {
3
+ started: boolean;
4
+ posthog: PostHog | null;
5
+ pending: [unknown, Record<string, unknown> | undefined][];
6
+ loadPosthog: () => Promise<{
7
+ default: PostHog;
8
+ }>;
9
+ };
10
+ /** PostHog options for error tracking only: exceptions are sent, nothing else is. Pure, so the test can lock the mapping. */
11
+ export declare function buildErrorTrackingInitOptions({ host }: {
12
+ host: string;
13
+ }): Parameters<PostHog["init"]>[1];
14
+ /**
15
+ * Starts exception tracking in the browser, once per page. No initConsent is needed: nothing is
16
+ * stored on the device (memory persistence), no person is profiled and only exceptions are sent.
17
+ * Call it in the browser, once per page; in Next.js that is inside a useEffect in _app.
18
+ * Nothing starts when disabled, in Local, or when a host, client key, product or environment is missing.
19
+ */
20
+ export declare function initErrorTracking({ host, clientKey, product, surface, environment, release, enabled, }?: {
21
+ host?: string;
22
+ clientKey?: string;
23
+ product?: string;
24
+ surface?: string | undefined;
25
+ environment?: string;
26
+ release?: string | undefined;
27
+ enabled?: boolean;
28
+ }): void;
29
+ /**
30
+ * Reports an exception the page caught itself, such as one stopped by a React error boundary,
31
+ * which never reaches the global handlers. Does nothing unless initErrorTracking has started.
32
+ */
33
+ export declare function captureBrowserException(error: unknown, properties?: Record<string, unknown>): void;
34
+ export declare function resetErrorTrackingForTests(loadPosthog?: ErrorState["loadPosthog"]): void;
35
+ export {};
@@ -0,0 +1,19 @@
1
+ import type { FleetEventName } from "./vocabulary.ts";
2
+ /** A value PostHog can store and a JSON event body can carry. */
3
+ export type EventPropertyValue = string | number | boolean | null | EventPropertyValue[] | {
4
+ [key: string]: EventPropertyValue;
5
+ };
6
+ /** The properties an event, identify or group call carries. */
7
+ export type EventProperties = {
8
+ [key: string]: EventPropertyValue;
9
+ };
10
+ export type EventName = FleetEventName | (string & Record<never, never>);
11
+ /**
12
+ * The event names an entry may send: the fleet vocabulary plus every name the product registers.
13
+ * Each entry owns one, kept outside its session state, because an event name belongs to the
14
+ * product's vocabulary rather than to one analytics session.
15
+ */
16
+ export declare function createEventRegistry(): {
17
+ register(names: Iterable<string>): void;
18
+ assertRegistered(name: EventName): void;
19
+ };
@@ -0,0 +1,26 @@
1
+ import type { PostHog } from "posthog-js";
2
+ /**
3
+ * Whether a PostHog feature flag is on for this person. False whenever the answer cannot be
4
+ * trusted: flags not turned on in initAnalytics, analytics off or Local, no analytics consent
5
+ * (a revoke included), or PostHog still loading. A PostHog failure also reads as false, the default
6
+ * for the current render, but is never silent: it is sent to the logger passed to initAnalytics and
7
+ * rethrown on its own turn so the page's error reporting sees it. PostHog's own call records the
8
+ * exposure as $feature_flag_called. Never throws into the caller's own turn.
9
+ */
10
+ export declare function isFeatureEnabled(key: string): boolean;
11
+ /**
12
+ * The flag's value: the variant key for a multivariate flag (an experiment), true or false for a
13
+ * plain one. Null under the same conditions as isFeatureEnabled returns false, and for an unknown
14
+ * flag. A PostHog failure reads as null for the current render, is sent to the logger and rethrown
15
+ * on its own turn, as isFeatureEnabled does; records the exposure like isFeatureEnabled.
16
+ */
17
+ export declare function getFeatureFlag(key: string): string | boolean | null;
18
+ /**
19
+ * Calls listener whenever flags become readable: when PostHog loads or reloads them (after
20
+ * consent, identify, group). When they cannot load now (flags off, analytics off, no consent) it
21
+ * is called once on the next turn, so a screen waiting on it renders its default instead of
22
+ * waiting forever. Read the values inside it with isFeatureEnabled or getFeatureFlag. Returns an
23
+ * unsubscribe function that works at any time, before initAnalytics included.
24
+ */
25
+ export declare function onFeatureFlags(listener: () => void): () => boolean;
26
+ export declare function followFeatureFlags(posthog: PostHog): void;
@@ -0,0 +1,5 @@
1
+ export { group, identify, initAnalytics, resetIdentity, trackEvent, WORKSPACE_GROUP_TYPE } from "./analytics.ts";
2
+ export { getFeatureFlag, isFeatureEnabled, onFeatureFlags } from "./feature-flags.ts";
3
+ export { CONSENT_CHANGE_EVENT, CONSENT_COOKIE_NAME, captureAttribution, channels, events, getAttribution, getConsent, initConsent, loadTags, onConsentChange, registerEvents, requiresOptIn, resolveAiSource, resolveChannel, saveConsent, setConsentRegion, trackSiteEvent, } from "./site.ts";
4
+ export { trackTours } from "./tours.ts";
5
+ export { track } from "./track-helpers.ts";
@@ -0,0 +1,38 @@
1
+ import { PostHog } from "posthog-node";
2
+ type NodeErrorState = {
3
+ client: PostHog | null;
4
+ base: Record<string, unknown>;
5
+ createClient: (key: string, options: NonNullable<ConstructorParameters<typeof PostHog>[1]>) => PostHog;
6
+ };
7
+ /**
8
+ * Starts exception tracking on the server, once per process. Nothing starts when disabled, in Local,
9
+ * when already started, or when a host, client key, product or environment is missing.
10
+ * captureUncaught also reports uncaught exceptions and unhandled rejections.
11
+ */
12
+ export declare function initServerErrorTracking({ host, clientKey, product, surface, environment, release, enabled, captureUncaught, }?: {
13
+ host?: string;
14
+ clientKey?: string;
15
+ product?: string;
16
+ surface?: string | undefined;
17
+ environment?: string;
18
+ release?: string | undefined;
19
+ enabled?: boolean;
20
+ captureUncaught?: boolean;
21
+ }): void;
22
+ /** Sends an exception with the request it came from. Does nothing until initServerErrorTracking has run. */
23
+ export declare function captureServerException(error: unknown, { distinctId, path, method, statusCode, properties, }?: {
24
+ distinctId?: string;
25
+ path?: string;
26
+ method?: string;
27
+ statusCode?: unknown;
28
+ properties?: Record<string, unknown>;
29
+ }): void;
30
+ /** Express error middleware: records the error, then passes it on so Express answers as it would without tracking. */
31
+ export declare function expressErrorHandler(): (err: unknown, req: {
32
+ originalUrl: string;
33
+ method: string;
34
+ }, _res: unknown, next: (err: unknown) => void) => void;
35
+ /** Sends what is queued and stops the client, within timeoutMs. Call it on shutdown, before the process exits. */
36
+ export declare function flushServerErrorTracking(timeoutMs?: number): Promise<void>;
37
+ export declare function resetServerErrorTrackingForTests(createClient?: NodeErrorState["createClient"]): void;
38
+ export {};
@@ -0,0 +1 @@
1
+ export { captureServerException, expressErrorHandler, flushServerErrorTracking, initServerErrorTracking, resetServerErrorTrackingForTests, } from "./errors.ts";
@@ -0,0 +1,22 @@
1
+ import type { PostHog, PostHogConfig } from "posthog-js";
2
+ import { type ResolvedAnalyticsConfig } from "./state.ts";
3
+ export type PosthogInitOptions = Partial<PostHogConfig> & Record<string, unknown>;
4
+ /** What buildInitOptions reads from a config: initAnalytics passes its resolved config, initSiteAnalytics only these. */
5
+ export type PosthogInitConfig = Pick<ResolvedAnalyticsConfig, "host" | "heatmaps" | "captureExceptions"> & {
6
+ sessionRecording?: ResolvedAnalyticsConfig["sessionRecording"] | undefined;
7
+ featureFlags?: boolean | undefined;
8
+ };
9
+ export declare function ensurePosthogInitialized(): Promise<PostHog>;
10
+ /**
11
+ * Copies init options and, when consent is absent, sets the flag that keeps init itself
12
+ * from capturing. Pure so the smoke test can lock the consent decision without a browser.
13
+ * With the product's flags on it also holds the first flags request: opting out does not stop
14
+ * posthog-js asking for flags, and that request names the visitor. The grant reloads them.
15
+ */
16
+ export declare function applyConsentToInitOptions(options: PosthogInitOptions, consentGranted: boolean, featureFlags?: boolean): PosthogInitOptions;
17
+ /**
18
+ * The posthog-js init options for a config. Pure, so the smoke test can assert the mapping
19
+ * without a browser: replay stays off unless the product enabled it, and the masking choices
20
+ * ride through only when it is on.
21
+ */
22
+ export declare function buildInitOptions(config: PosthogInitConfig): PosthogInitOptions;
@@ -0,0 +1,90 @@
1
+ import type { AnalyticsLogger } from "../analytics.ts";
2
+ import type { EventName, EventProperties } from "../event-registry.ts";
3
+ import { events } from "../vocabulary.ts";
4
+ export { __setNativeModulesForTests } from "./native-modules.ts";
5
+ export { events };
6
+ export declare const CONSENT_STORAGE_KEY = "webority_analytics_consent";
7
+ declare const REGIONS: readonly ["eea", "other"];
8
+ type ConsentRegion = (typeof REGIONS)[number];
9
+ export declare const WORKSPACE_GROUP_TYPE = "workspace";
10
+ type KeyValueStorage = {
11
+ getItem(key: string): Promise<string | null>;
12
+ setItem(key: string, value: string): Promise<void>;
13
+ };
14
+ type MobileInit = {
15
+ host?: string;
16
+ clientKey?: string;
17
+ product?: string;
18
+ surface?: string;
19
+ environment?: string;
20
+ enabled?: boolean;
21
+ logger?: AnalyticsLogger;
22
+ storage?: KeyValueStorage;
23
+ featureFlags?: boolean;
24
+ requiresOptIn?: boolean;
25
+ };
26
+ type MobileConsent = {
27
+ analytics: boolean;
28
+ decided: boolean;
29
+ };
30
+ /**
31
+ * Reads the stored choice and, when the config is complete and not Local, starts PostHog opted
32
+ * out. It opts in only while analytics consent holds. requiresOptIn comes from the person's
33
+ * country, as on the web; with no stored choice and opt-in required, nothing is sent until
34
+ * setConsentRegion("other") or setAnalyticsConsent(true). Resolves once PostHog is ready, never rejects.
35
+ */
36
+ export declare function initMobileAnalytics(config?: MobileInit): Promise<void>;
37
+ /**
38
+ * Applies the person's region when the app learns it. "other" grants analytics by default when
39
+ * no choice is stored; "eea" keeps opt-in. Listeners fire only when the effective consent changes.
40
+ */
41
+ export declare function setConsentRegion(region: ConsentRegion): void;
42
+ /** Stores the person's choice, opts PostHog in or out, and notifies every listener. Never rejects. */
43
+ export declare function setAnalyticsConsent(granted: boolean): Promise<void>;
44
+ /**
45
+ * The current consent. Before a choice (decided: false) analytics follows the region default,
46
+ * except after a stored choice that could not be read: that is no consent, whatever the region.
47
+ */
48
+ export declare function getAnalyticsConsent(): MobileConsent;
49
+ /** Calls listener with the new consent whenever it changes. Returns an unsubscribe function. */
50
+ export declare function onAnalyticsConsentChange(listener: (consent: MobileConsent) => void): () => boolean;
51
+ /**
52
+ * Names the person by their PublicId, never an internal id or an email. Made before consent, it
53
+ * is kept and applied when analytics is allowed; only the last one is kept.
54
+ */
55
+ export declare function identify(publicId: string, props?: EventProperties): void;
56
+ /**
57
+ * Ties the person's later events to a PostHog group and sets the group's properties (plan,
58
+ * seats): group(WORKSPACE_GROUP_TYPE, workspacePublicId, props). PublicId strings only; a number
59
+ * throws, because an internal id never reaches analytics. Held like identify, one per type, and
60
+ * forgotten by resetIdentity.
61
+ */
62
+ export declare function group(type: string, key: string, props?: EventProperties): void;
63
+ /**
64
+ * Whether a PostHog feature flag is on for this person. False whenever the answer cannot be
65
+ * trusted: flags not turned on in initMobileAnalytics, analytics off or Local, no consent, or
66
+ * PostHog still starting. A PostHog failure also reads as false for this render: it is sent to the
67
+ * logger passed to initMobileAnalytics and rethrown on its own turn.
68
+ * PostHog's own call records the exposure as $feature_flag_called.
69
+ */
70
+ export declare function isFeatureEnabled(key: string): boolean;
71
+ /**
72
+ * The flag's value: the variant key for a multivariate flag (an experiment), true or false for a
73
+ * plain one. Null when isFeatureEnabled would return false for the same reason, and for an
74
+ * unknown flag. A PostHog failure reads as null for this render, is sent to the logger and rethrown
75
+ * on its own turn, as isFeatureEnabled does; records the exposure like isFeatureEnabled.
76
+ */
77
+ export declare function getFeatureFlag(key: string): string | boolean | null;
78
+ /**
79
+ * Calls listener whenever flags become readable (after consent, identify, group). When they
80
+ * cannot load now (flags off, analytics off, no consent) it is called once on the next turn, so a
81
+ * screen waiting on it renders its default. Returns an unsubscribe function.
82
+ */
83
+ export declare function onFeatureFlags(listener: () => void): () => boolean;
84
+ export declare function resetIdentity(): void;
85
+ export declare function registerEvents(names: readonly string[]): void;
86
+ export declare function trackEvent(name: EventName, props?: EventProperties): void;
87
+ /** Sends a PostHog $screen view. Screen names are not event names, so they need no registration. */
88
+ export declare function trackScreen(screenName: string, props?: EventProperties): void;
89
+ /** Puts the module back to its first-load state for the smoke test. Not part of the public API. */
90
+ export declare function __resetForTests(): void;
@@ -0,0 +1,41 @@
1
+ type PostHogClient = {
2
+ ready?(): unknown;
3
+ register(props: Record<string, unknown>): unknown;
4
+ identify(publicId: string, props: Record<string, unknown>): unknown;
5
+ group(type: string, key: string, props: Record<string, unknown>): unknown;
6
+ capture(name: string, props: Record<string, unknown>): unknown;
7
+ screen(name: string, props: Record<string, unknown>): unknown;
8
+ optIn(): unknown;
9
+ optOut(): unknown;
10
+ reset(): unknown;
11
+ isFeatureEnabled(key: string): boolean | undefined;
12
+ getFeatureFlag(key: string): string | boolean | undefined;
13
+ onFeatureFlags?(listener: () => void): unknown;
14
+ reloadFeatureFlagsAsync?(): unknown;
15
+ };
16
+ type PostHogConstructor = new (apiKey: string, options: ReturnType<typeof buildNativeOptions>) => PostHogClient;
17
+ /**
18
+ * Replaces posthog-react-native for the smoke test, which runs under plain node.
19
+ * Not part of the public API. Pass null to go back to the real modules.
20
+ */
21
+ export declare function __setNativeModulesForTests(modules: unknown): void;
22
+ export declare function loadPostHogClass(): Promise<PostHogConstructor | null>;
23
+ export declare function isMissingModule(error: unknown): boolean;
24
+ /**
25
+ * The posthog-react-native constructor options for a config. Pure, so the smoke test can lock
26
+ * the privacy choices without a device.
27
+ */
28
+ export declare function buildNativeOptions(config: {
29
+ host: string;
30
+ featureFlags: boolean;
31
+ }): {
32
+ host: string;
33
+ defaultOptIn: boolean;
34
+ personProfiles: string;
35
+ captureAppLifecycleEvents: boolean;
36
+ enableSessionReplay: boolean;
37
+ preloadFeatureFlags: boolean;
38
+ disableRemoteFeatureFlags: boolean;
39
+ disableSurveys: boolean;
40
+ };
41
+ export {};
@@ -0,0 +1,16 @@
1
+ import type { EventName, EventProperties } from "./event-registry.ts";
2
+ declare global {
3
+ interface Window {
4
+ dataLayer?: unknown[];
5
+ }
6
+ }
7
+ /**
8
+ * Pushes a catalogue event (lead_submitted, whatsapp_click, calculator_use, phone_click...) to
9
+ * dataLayer for a Tag Manager trigger, carrying the visitor's first and last acquisition channel
10
+ * and ai_source. Nothing is pushed until the visitor has granted analytics consent; a name that is
11
+ * neither in the catalogue nor passed to registerEvents throws. When initSiteAnalytics has run, the
12
+ * event goes to PostHog too, held until PostHog starts, cookieless and anonymous without consent,
13
+ * as on the portal. Returns whether it was pushed to dataLayer.
14
+ */
15
+ export declare function trackSiteEvent(name: EventName, props?: EventProperties): boolean;
16
+ export declare function registerEvents(names: Iterable<EventName>): void;
@@ -0,0 +1,27 @@
1
+ declare const QUEUED_METHODS: readonly ["capture", "register", "opt_in_capturing", "opt_out_capturing"];
2
+ type QueuedMethod = (typeof QUEUED_METHODS)[number];
3
+ type SnippetOptions = {
4
+ api_host: string;
5
+ };
6
+ type SnippetMethods = {
7
+ [method in QueuedMethod]: (...args: unknown[]) => void;
8
+ };
9
+ type SnippetParts = SnippetMethods & {
10
+ _i: unknown[];
11
+ __SV: number;
12
+ people: unknown[];
13
+ init: (token: string, options: SnippetOptions) => void;
14
+ };
15
+ type SnippetQueue = unknown[] & SnippetParts;
16
+ type SnippetApi = {
17
+ init: (token: string, options: SnippetOptions) => void;
18
+ } & {
19
+ [method in QueuedMethod]?: (...args: unknown[]) => void;
20
+ };
21
+ declare global {
22
+ interface Window {
23
+ posthog?: SnippetQueue;
24
+ }
25
+ }
26
+ declare const posthog: SnippetApi;
27
+ export default posthog;