@codaco/analytics 9.0.0 → 9.0.1

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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,29 @@
1
1
  # @codaco/analytics
2
2
 
3
+ ## 9.0.1
4
+
5
+ ### Patch Changes
6
+
7
+ - cb70e1f: Bump posthog-js to 1.304.0
8
+
9
+ **architect-vite (private):**
10
+
11
+ - Add PostHog analytics tracking with Redux middleware for protocol events:
12
+ - Protocol opened
13
+ - Protocol previewed
14
+ - Stage added (with stage type)
15
+ - Protocol validation failed (with Zod-formatted error details)
16
+ - Protocol downloaded
17
+ - Enable session replay, pageview tracking, and automatic exception capture
18
+ - Add error tracking to AppErrorBoundary component
19
+ - Enable PostHog debug logging in development mode
20
+
21
+ **posthog-proxy-worker (private):**
22
+
23
+ - Simplify and refactor the Cloudflare Worker proxy implementation
24
+ - Add caching for static assets
25
+ - Forward client IP via X-Forwarded-For header
26
+
3
27
  ## 10.0.0
4
28
 
5
29
  ### Major Changes
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { A as AnalyticsConfig, a as Analytics } from './types-Ymgjicqi.js';
2
- export { E as ErrorProperties, b as EventProperties, c as EventType, e as eventTypes, l as legacyEventTypeMap } from './types-Ymgjicqi.js';
1
+ import { A as AnalyticsConfig, a as Analytics } from './types-DK5BiTnW.js';
2
+ export { E as ErrorProperties, b as EventProperties, c as EventType, e as eventTypes, l as legacyEventTypeMap } from './types-DK5BiTnW.js';
3
3
  import * as react from 'react';
4
4
  import { ReactNode } from 'react';
5
5
  import 'zod';
@@ -86,10 +86,10 @@ declare function useFeatureFlagValue(flagKey: string): string | boolean | undefi
86
86
  /**
87
87
  * Props for the AnalyticsProvider
88
88
  */
89
- interface AnalyticsProviderProps {
89
+ type AnalyticsProviderProps = {
90
90
  children: ReactNode;
91
91
  config: AnalyticsConfig;
92
- }
92
+ };
93
93
  /**
94
94
  * Provider component that initializes PostHog and provides analytics context
95
95
  *
package/dist/index.js CHANGED
@@ -169,7 +169,7 @@ function useFeatureFlagValue(flagKey) {
169
169
  }
170
170
 
171
171
  // src/types.ts
172
- import z from "zod";
172
+ import { z } from "zod";
173
173
  var eventTypes = [
174
174
  "app_setup",
175
175
  "protocol_installed",
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/hooks.ts","../src/provider.tsx","../src/client.ts","../src/types.ts"],"sourcesContent":["\"use client\";\n\nimport { useContext } from \"react\";\nimport { AnalyticsContext } from \"./provider\";\nimport type { Analytics } from \"./types\";\n\n/**\n * Hook to access analytics functionality in React components\n *\n * @example\n * ```tsx\n * import { useAnalytics } from '@codaco/analytics';\n *\n * function MyComponent() {\n * const { trackEvent, trackError } = useAnalytics();\n *\n * const handleAction = () => {\n * trackEvent('protocol_installed', {\n * metadata: { protocolName: 'My Protocol' }\n * });\n * };\n *\n * return <button onClick={handleAction}>Install Protocol</button>;\n * }\n * ```\n */\nexport function useAnalytics(): Analytics {\n\tconst analytics = useContext(AnalyticsContext);\n\n\tif (!analytics) {\n\t\tthrow new Error(\"useAnalytics must be used within an AnalyticsProvider\");\n\t}\n\n\treturn analytics;\n}\n\n/**\n * Hook to access feature flags\n *\n * @example\n * ```tsx\n * import { useFeatureFlag } from '@codaco/analytics';\n *\n * function MyComponent() {\n * const isNewFeatureEnabled = useFeatureFlag('new-feature');\n *\n * if (isNewFeatureEnabled) {\n * return <NewFeature />;\n * }\n *\n * return <OldFeature />;\n * }\n * ```\n */\nexport function useFeatureFlag(flagKey: string): boolean {\n\tconst analytics = useAnalytics();\n\treturn analytics.isFeatureEnabled(flagKey) ?? false;\n}\n\n/**\n * Hook to access feature flag values (for multivariate flags)\n *\n * @example\n * ```tsx\n * import { useFeatureFlagValue } from '@codaco/analytics';\n *\n * function MyComponent() {\n * const theme = useFeatureFlagValue('theme-variant');\n *\n * return <div className={theme === 'dark' ? 'dark-theme' : 'light-theme'}>\n * Content\n * </div>;\n * }\n * ```\n */\nexport function useFeatureFlagValue(flagKey: string): string | boolean | undefined {\n\tconst analytics = useAnalytics();\n\treturn analytics.getFeatureFlag(flagKey);\n}\n","\"use client\";\n\nimport { createContext, type ReactNode, useEffect, useRef } from \"react\";\nimport { createAnalytics } from \"./client\";\nimport { mergeConfig } from \"./config\";\nimport type { Analytics, AnalyticsConfig } from \"./types\";\n\n/**\n * React Context for analytics\n */\nexport const AnalyticsContext = createContext<Analytics | null>(null);\n\n/**\n * Props for the AnalyticsProvider\n */\nexport interface AnalyticsProviderProps {\n\tchildren: ReactNode;\n\tconfig: AnalyticsConfig;\n}\n\n/**\n * Provider component that initializes PostHog and provides analytics context\n *\n * @example\n * ```tsx\n * import { AnalyticsProvider } from '@codaco/analytics';\n *\n * function App({ children }) {\n * return (\n * <AnalyticsProvider\n * config={{\n * installationId: 'your-installation-id',\n * apiKey: 'phc_your_api_key', // optional if set via env\n * apiHost: 'https://ph-relay.networkcanvas.com', // optional\n * }}\n * >\n * {children}\n * </AnalyticsProvider>\n * );\n * }\n * ```\n */\nexport function AnalyticsProvider({ children, config }: AnalyticsProviderProps) {\n\tconst analyticsRef = useRef<Analytics | null>(null);\n\n\t// Initialize analytics only once\n\tuseEffect(() => {\n\t\tif (!analyticsRef.current) {\n\t\t\tconst mergedConfig = mergeConfig(config);\n\t\t\tanalyticsRef.current = createAnalytics(mergedConfig);\n\t\t}\n\t}, []); // Empty deps - only initialize once\n\n\t// Don't render children until analytics is initialized\n\tif (!analyticsRef.current) {\n\t\treturn null;\n\t}\n\n\treturn <AnalyticsContext.Provider value={analyticsRef.current}>{children}</AnalyticsContext.Provider>;\n}\n","import posthog from \"posthog-js\";\nimport type { Analytics, AnalyticsConfig, ErrorProperties, EventProperties, EventType } from \"./types\";\nimport { ensureError } from \"./utils\";\n\n/**\n * Create a client-side analytics instance\n * This wraps PostHog with Network Canvas-specific functionality\n */\nexport function createAnalytics(config: Required<AnalyticsConfig>): Analytics {\n\tconst { apiHost, apiKey, installationId, disabled, debug, posthogOptions } = config;\n\n\t// If analytics is disabled, return a no-op implementation\n\tif (disabled) {\n\t\treturn createNoOpAnalytics(installationId);\n\t}\n\n\t// Initialize PostHog\n\tposthog.init(apiKey, {\n\t\tapi_host: apiHost,\n\t\tloaded: (posthogInstance) => {\n\t\t\t// Set installation ID as a super property (included with every event)\n\t\t\tposthogInstance.register({\n\t\t\t\tinstallation_id: installationId,\n\t\t\t});\n\n\t\t\tif (debug) {\n\t\t\t\tposthogInstance.debug();\n\t\t\t}\n\t\t},\n\t\t...posthogOptions,\n\t});\n\n\treturn {\n\t\ttrackEvent: (eventType: EventType | string, properties?: EventProperties) => {\n\t\t\tif (disabled) return;\n\n\t\t\ttry {\n\t\t\t\tposthog.capture(eventType, {\n\t\t\t\t\t...properties,\n\t\t\t\t\t// Flatten metadata into properties for better PostHog integration\n\t\t\t\t\t...(properties?.metadata ?? {}),\n\t\t\t\t});\n\t\t\t} catch (_e) {\n\t\t\t\tif (debug) {\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\ttrackError: (error: Error, additionalProperties?: EventProperties) => {\n\t\t\tif (disabled) return;\n\n\t\t\ttry {\n\t\t\t\tconst errorObj = ensureError(error);\n\t\t\t\tconst errorProperties: ErrorProperties = {\n\t\t\t\t\tmessage: errorObj.message,\n\t\t\t\t\tname: errorObj.name,\n\t\t\t\t\tstack: errorObj.stack,\n\t\t\t\t\tcause: errorObj.cause ? String(errorObj.cause) : undefined,\n\t\t\t\t\t...additionalProperties,\n\t\t\t\t};\n\n\t\t\t\tposthog.capture(\"error\", {\n\t\t\t\t\t...errorProperties,\n\t\t\t\t\t// Flatten metadata\n\t\t\t\t\t...(additionalProperties?.metadata ?? {}),\n\t\t\t\t});\n\t\t\t} catch (_e) {\n\t\t\t\tif (debug) {\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\tisFeatureEnabled: (flagKey: string) => {\n\t\t\tif (disabled) return false;\n\n\t\t\ttry {\n\t\t\t\treturn posthog.isFeatureEnabled(flagKey);\n\t\t\t} catch (_e) {\n\t\t\t\tif (debug) {\n\t\t\t\t}\n\t\t\t\treturn undefined;\n\t\t\t}\n\t\t},\n\n\t\tgetFeatureFlag: (flagKey: string) => {\n\t\t\tif (disabled) return undefined;\n\n\t\t\ttry {\n\t\t\t\treturn posthog.getFeatureFlag(flagKey);\n\t\t\t} catch (_e) {\n\t\t\t\tif (debug) {\n\t\t\t\t}\n\t\t\t\treturn undefined;\n\t\t\t}\n\t\t},\n\n\t\treloadFeatureFlags: () => {\n\t\t\tif (disabled) return;\n\n\t\t\ttry {\n\t\t\t\tposthog.reloadFeatureFlags();\n\t\t\t} catch (_e) {\n\t\t\t\tif (debug) {\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\tidentify: (distinctId: string, properties?: Record<string, unknown>) => {\n\t\t\tif (disabled) return;\n\n\t\t\ttry {\n\t\t\t\tposthog.identify(distinctId, properties);\n\t\t\t} catch (_e) {\n\t\t\t\tif (debug) {\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\treset: () => {\n\t\t\tif (disabled) return;\n\n\t\t\ttry {\n\t\t\t\tposthog.reset();\n\t\t\t} catch (_e) {\n\t\t\t\tif (debug) {\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\tisEnabled: () => !disabled,\n\n\t\tgetInstallationId: () => installationId,\n\t};\n}\n\n/**\n * Create a no-op analytics instance when analytics is disabled\n */\nfunction createNoOpAnalytics(installationId: string): Analytics {\n\treturn {\n\t\ttrackEvent: () => {},\n\t\ttrackError: () => {},\n\t\tisFeatureEnabled: () => false,\n\t\tgetFeatureFlag: () => undefined,\n\t\treloadFeatureFlags: () => {},\n\t\tidentify: () => {},\n\t\treset: () => {},\n\t\tisEnabled: () => false,\n\t\tgetInstallationId: () => installationId,\n\t};\n}\n","import z from \"zod\";\n\n/**\n * Event types supported by the analytics system.\n * These are converted to snake_case for PostHog.\n */\nexport const eventTypes = [\n\t\"app_setup\",\n\t\"protocol_installed\",\n\t\"interview_started\",\n\t\"interview_completed\",\n\t\"data_exported\",\n\t\"error\",\n] as const;\n\nexport type EventType = (typeof eventTypes)[number];\n\n/**\n * Legacy event type mapping for backward compatibility\n */\nexport const legacyEventTypeMap: Record<string, EventType> = {\n\tAppSetup: \"app_setup\",\n\tProtocolInstalled: \"protocol_installed\",\n\tInterviewStarted: \"interview_started\",\n\tInterviewCompleted: \"interview_completed\",\n\tDataExported: \"data_exported\",\n\tError: \"error\",\n};\n\n/**\n * Standard event properties that can be sent with any event\n */\nexport const EventPropertiesSchema = z.object({\n\tmetadata: z.record(z.string(), z.unknown()).optional(),\n});\n\nexport type EventProperties = z.infer<typeof EventPropertiesSchema>;\n\n/**\n * Error-specific properties for error tracking\n */\nexport const ErrorPropertiesSchema = EventPropertiesSchema.extend({\n\tmessage: z.string(),\n\tname: z.string(),\n\tstack: z.string().optional(),\n\tcause: z.string().optional(),\n});\n\nexport type ErrorProperties = z.infer<typeof ErrorPropertiesSchema>;\n\n/**\n * Analytics configuration options\n *\n * This package is designed to work exclusively with the Cloudflare Worker\n * reverse proxy at ph-relay.networkcanvas.com. All authentication is handled\n * by the worker, so the API key is optional.\n */\nexport interface AnalyticsConfig {\n\t/**\n\t * PostHog API host - should point to the Cloudflare Worker reverse proxy\n\t * Defaults to \"https://ph-relay.networkcanvas.com\"\n\t */\n\tapiHost?: string;\n\n\t/**\n\t * PostHog project API key (optional)\n\t *\n\t * When using the reverse proxy (default), authentication is handled by the\n\t * Cloudflare Worker. A placeholder key will be used for client-side PostHog\n\t * initialization if not provided.\n\t *\n\t * Only set this if you need to override the default behavior.\n\t */\n\tapiKey?: string;\n\n\t/**\n\t * Unique identifier for this installation/deployment\n\t * This is included with every event as a super property\n\t */\n\tinstallationId: string;\n\n\t/**\n\t * Disable all analytics tracking\n\t * Can be set via DISABLE_ANALYTICS or NEXT_PUBLIC_DISABLE_ANALYTICS env var\n\t */\n\tdisabled?: boolean;\n\n\t/**\n\t * Enable debug mode for PostHog\n\t */\n\tdebug?: boolean;\n\n\t/**\n\t * Additional options to pass to PostHog initialization\n\t */\n\tposthogOptions?: {\n\t\t/**\n\t\t * Disable session recording\n\t\t */\n\t\tdisable_session_recording?: boolean;\n\n\t\t/**\n\t\t * Autocapture settings\n\t\t */\n\t\tautocapture?: boolean;\n\n\t\t/**\n\t\t * Capture pageviews automatically\n\t\t */\n\t\tcapture_pageview?: boolean;\n\n\t\t/**\n\t\t * Capture pageleave events\n\t\t */\n\t\tcapture_pageleave?: boolean;\n\n\t\t/**\n\t\t * Cross-subdomain cookie\n\t\t */\n\t\tcross_subdomain_cookie?: boolean;\n\n\t\t/**\n\t\t * Advanced feature flags support\n\t\t */\n\t\tadvanced_disable_feature_flags?: boolean;\n\n\t\t/**\n\t\t * Other PostHog options\n\t\t */\n\t\t[key: string]: unknown;\n\t};\n}\n\n/**\n * Analytics instance interface\n */\nexport interface Analytics {\n\t/**\n\t * Track a custom event\n\t */\n\ttrackEvent: (eventType: EventType | string, properties?: EventProperties) => void;\n\n\t/**\n\t * Track an error with full stack trace\n\t */\n\ttrackError: (error: Error, additionalProperties?: EventProperties) => void;\n\n\t/**\n\t * Check if a feature flag is enabled\n\t */\n\tisFeatureEnabled: (flagKey: string) => boolean | undefined;\n\n\t/**\n\t * Get the value of a feature flag\n\t */\n\tgetFeatureFlag: (flagKey: string) => string | boolean | undefined;\n\n\t/**\n\t * Reload feature flags from PostHog\n\t */\n\treloadFeatureFlags: () => void;\n\n\t/**\n\t * Identify a user (optional - for advanced use cases)\n\t * Note: By default we only track installations, not users\n\t */\n\tidentify: (distinctId: string, properties?: Record<string, unknown>) => void;\n\n\t/**\n\t * Reset the user identity\n\t */\n\treset: () => void;\n\n\t/**\n\t * Check if analytics is enabled\n\t */\n\tisEnabled: () => boolean;\n\n\t/**\n\t * Get the installation ID\n\t */\n\tgetInstallationId: () => string;\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/hooks.ts","../src/provider.tsx","../src/client.ts","../src/types.ts"],"sourcesContent":["\"use client\";\n\nimport { useContext } from \"react\";\nimport { AnalyticsContext } from \"./provider\";\nimport type { Analytics } from \"./types\";\n\n/**\n * Hook to access analytics functionality in React components\n *\n * @example\n * ```tsx\n * import { useAnalytics } from '@codaco/analytics';\n *\n * function MyComponent() {\n * const { trackEvent, trackError } = useAnalytics();\n *\n * const handleAction = () => {\n * trackEvent('protocol_installed', {\n * metadata: { protocolName: 'My Protocol' }\n * });\n * };\n *\n * return <button onClick={handleAction}>Install Protocol</button>;\n * }\n * ```\n */\nexport function useAnalytics(): Analytics {\n\tconst analytics = useContext(AnalyticsContext);\n\n\tif (!analytics) {\n\t\tthrow new Error(\"useAnalytics must be used within an AnalyticsProvider\");\n\t}\n\n\treturn analytics;\n}\n\n/**\n * Hook to access feature flags\n *\n * @example\n * ```tsx\n * import { useFeatureFlag } from '@codaco/analytics';\n *\n * function MyComponent() {\n * const isNewFeatureEnabled = useFeatureFlag('new-feature');\n *\n * if (isNewFeatureEnabled) {\n * return <NewFeature />;\n * }\n *\n * return <OldFeature />;\n * }\n * ```\n */\nexport function useFeatureFlag(flagKey: string): boolean {\n\tconst analytics = useAnalytics();\n\treturn analytics.isFeatureEnabled(flagKey) ?? false;\n}\n\n/**\n * Hook to access feature flag values (for multivariate flags)\n *\n * @example\n * ```tsx\n * import { useFeatureFlagValue } from '@codaco/analytics';\n *\n * function MyComponent() {\n * const theme = useFeatureFlagValue('theme-variant');\n *\n * return <div className={theme === 'dark' ? 'dark-theme' : 'light-theme'}>\n * Content\n * </div>;\n * }\n * ```\n */\nexport function useFeatureFlagValue(flagKey: string): string | boolean | undefined {\n\tconst analytics = useAnalytics();\n\treturn analytics.getFeatureFlag(flagKey);\n}\n","\"use client\";\n\nimport { createContext, type ReactNode, useEffect, useRef } from \"react\";\nimport { createAnalytics } from \"./client\";\nimport { mergeConfig } from \"./config\";\nimport type { Analytics, AnalyticsConfig } from \"./types\";\n\n/**\n * React Context for analytics\n */\nexport const AnalyticsContext = createContext<Analytics | null>(null);\n\n/**\n * Props for the AnalyticsProvider\n */\nexport type AnalyticsProviderProps = {\n\tchildren: ReactNode;\n\tconfig: AnalyticsConfig;\n};\n\n/**\n * Provider component that initializes PostHog and provides analytics context\n *\n * @example\n * ```tsx\n * import { AnalyticsProvider } from '@codaco/analytics';\n *\n * function App({ children }) {\n * return (\n * <AnalyticsProvider\n * config={{\n * installationId: 'your-installation-id',\n * apiKey: 'phc_your_api_key', // optional if set via env\n * apiHost: 'https://ph-relay.networkcanvas.com', // optional\n * }}\n * >\n * {children}\n * </AnalyticsProvider>\n * );\n * }\n * ```\n */\nexport function AnalyticsProvider({ children, config }: AnalyticsProviderProps) {\n\tconst analyticsRef = useRef<Analytics | null>(null);\n\n\t// Initialize analytics only once\n\tuseEffect(() => {\n\t\tif (!analyticsRef.current) {\n\t\t\tconst mergedConfig = mergeConfig(config);\n\t\t\tanalyticsRef.current = createAnalytics(mergedConfig);\n\t\t}\n\t}, []); // Empty deps - only initialize once\n\n\t// Don't render children until analytics is initialized\n\tif (!analyticsRef.current) {\n\t\treturn null;\n\t}\n\n\treturn <AnalyticsContext.Provider value={analyticsRef.current}>{children}</AnalyticsContext.Provider>;\n}\n","import posthog from \"posthog-js\";\nimport type { Analytics, AnalyticsConfig, ErrorProperties, EventProperties, EventType } from \"./types\";\nimport { ensureError } from \"./utils\";\n\n/**\n * Create a client-side analytics instance\n * This wraps PostHog with Network Canvas-specific functionality\n */\nexport function createAnalytics(config: Required<AnalyticsConfig>): Analytics {\n\tconst { apiHost, apiKey, installationId, disabled, debug, posthogOptions } = config;\n\n\t// If analytics is disabled, return a no-op implementation\n\tif (disabled) {\n\t\treturn createNoOpAnalytics(installationId);\n\t}\n\n\t// Initialize PostHog\n\tposthog.init(apiKey, {\n\t\tapi_host: apiHost,\n\t\tloaded: (posthogInstance) => {\n\t\t\t// Set installation ID as a super property (included with every event)\n\t\t\tposthogInstance.register({\n\t\t\t\tinstallation_id: installationId,\n\t\t\t});\n\n\t\t\tif (debug) {\n\t\t\t\tposthogInstance.debug();\n\t\t\t}\n\t\t},\n\t\t...posthogOptions,\n\t});\n\n\treturn {\n\t\ttrackEvent: (eventType: EventType | string, properties?: EventProperties) => {\n\t\t\tif (disabled) return;\n\n\t\t\ttry {\n\t\t\t\tposthog.capture(eventType, {\n\t\t\t\t\t...properties,\n\t\t\t\t\t// Flatten metadata into properties for better PostHog integration\n\t\t\t\t\t...(properties?.metadata ?? {}),\n\t\t\t\t});\n\t\t\t} catch (_e) {\n\t\t\t\tif (debug) {\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\ttrackError: (error: Error, additionalProperties?: EventProperties) => {\n\t\t\tif (disabled) return;\n\n\t\t\ttry {\n\t\t\t\tconst errorObj = ensureError(error);\n\t\t\t\tconst errorProperties: ErrorProperties = {\n\t\t\t\t\tmessage: errorObj.message,\n\t\t\t\t\tname: errorObj.name,\n\t\t\t\t\tstack: errorObj.stack,\n\t\t\t\t\tcause: errorObj.cause ? String(errorObj.cause) : undefined,\n\t\t\t\t\t...additionalProperties,\n\t\t\t\t};\n\n\t\t\t\tposthog.capture(\"error\", {\n\t\t\t\t\t...errorProperties,\n\t\t\t\t\t// Flatten metadata\n\t\t\t\t\t...(additionalProperties?.metadata ?? {}),\n\t\t\t\t});\n\t\t\t} catch (_e) {\n\t\t\t\tif (debug) {\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\tisFeatureEnabled: (flagKey: string) => {\n\t\t\tif (disabled) return false;\n\n\t\t\ttry {\n\t\t\t\treturn posthog.isFeatureEnabled(flagKey);\n\t\t\t} catch (_e) {\n\t\t\t\tif (debug) {\n\t\t\t\t}\n\t\t\t\treturn undefined;\n\t\t\t}\n\t\t},\n\n\t\tgetFeatureFlag: (flagKey: string) => {\n\t\t\tif (disabled) return undefined;\n\n\t\t\ttry {\n\t\t\t\treturn posthog.getFeatureFlag(flagKey);\n\t\t\t} catch (_e) {\n\t\t\t\tif (debug) {\n\t\t\t\t}\n\t\t\t\treturn undefined;\n\t\t\t}\n\t\t},\n\n\t\treloadFeatureFlags: () => {\n\t\t\tif (disabled) return;\n\n\t\t\ttry {\n\t\t\t\tposthog.reloadFeatureFlags();\n\t\t\t} catch (_e) {\n\t\t\t\tif (debug) {\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\tidentify: (distinctId: string, properties?: Record<string, unknown>) => {\n\t\t\tif (disabled) return;\n\n\t\t\ttry {\n\t\t\t\tposthog.identify(distinctId, properties);\n\t\t\t} catch (_e) {\n\t\t\t\tif (debug) {\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\treset: () => {\n\t\t\tif (disabled) return;\n\n\t\t\ttry {\n\t\t\t\tposthog.reset();\n\t\t\t} catch (_e) {\n\t\t\t\tif (debug) {\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\tisEnabled: () => !disabled,\n\n\t\tgetInstallationId: () => installationId,\n\t};\n}\n\n/**\n * Create a no-op analytics instance when analytics is disabled\n */\nfunction createNoOpAnalytics(installationId: string): Analytics {\n\treturn {\n\t\ttrackEvent: () => {},\n\t\ttrackError: () => {},\n\t\tisFeatureEnabled: () => false,\n\t\tgetFeatureFlag: () => undefined,\n\t\treloadFeatureFlags: () => {},\n\t\tidentify: () => {},\n\t\treset: () => {},\n\t\tisEnabled: () => false,\n\t\tgetInstallationId: () => installationId,\n\t};\n}\n","import { z } from \"zod\";\n\n/**\n * Event types supported by the analytics system.\n * These are converted to snake_case for PostHog.\n */\nexport const eventTypes = [\n\t\"app_setup\",\n\t\"protocol_installed\",\n\t\"interview_started\",\n\t\"interview_completed\",\n\t\"data_exported\",\n\t\"error\",\n] as const;\n\nexport type EventType = (typeof eventTypes)[number];\n\n/**\n * Legacy event type mapping for backward compatibility\n */\nexport const legacyEventTypeMap: Record<string, EventType> = {\n\tAppSetup: \"app_setup\",\n\tProtocolInstalled: \"protocol_installed\",\n\tInterviewStarted: \"interview_started\",\n\tInterviewCompleted: \"interview_completed\",\n\tDataExported: \"data_exported\",\n\tError: \"error\",\n};\n\n/**\n * Standard event properties that can be sent with any event\n */\nexport const EventPropertiesSchema = z.object({\n\tmetadata: z.record(z.string(), z.unknown()).optional(),\n});\n\nexport type EventProperties = z.infer<typeof EventPropertiesSchema>;\n\n/**\n * Error-specific properties for error tracking\n */\nexport const ErrorPropertiesSchema = EventPropertiesSchema.extend({\n\tmessage: z.string(),\n\tname: z.string(),\n\tstack: z.string().optional(),\n\tcause: z.string().optional(),\n});\n\nexport type ErrorProperties = z.infer<typeof ErrorPropertiesSchema>;\n\n/**\n * Analytics configuration options\n *\n * This package is designed to work exclusively with the Cloudflare Worker\n * reverse proxy at ph-relay.networkcanvas.com. All authentication is handled\n * by the worker, so the API key is optional.\n */\nexport type AnalyticsConfig = {\n\t/**\n\t * PostHog API host - should point to the Cloudflare Worker reverse proxy\n\t * Defaults to \"https://ph-relay.networkcanvas.com\"\n\t */\n\tapiHost?: string;\n\n\t/**\n\t * PostHog project API key (optional)\n\t *\n\t * When using the reverse proxy (default), authentication is handled by the\n\t * Cloudflare Worker. A placeholder key will be used for client-side PostHog\n\t * initialization if not provided.\n\t *\n\t * Only set this if you need to override the default behavior.\n\t */\n\tapiKey?: string;\n\n\t/**\n\t * Unique identifier for this installation/deployment\n\t * This is included with every event as a super property\n\t */\n\tinstallationId: string;\n\n\t/**\n\t * Disable all analytics tracking\n\t * Can be set via DISABLE_ANALYTICS or NEXT_PUBLIC_DISABLE_ANALYTICS env var\n\t */\n\tdisabled?: boolean;\n\n\t/**\n\t * Enable debug mode for PostHog\n\t */\n\tdebug?: boolean;\n\n\t/**\n\t * Additional options to pass to PostHog initialization\n\t */\n\tposthogOptions?: {\n\t\t/**\n\t\t * Disable session recording\n\t\t */\n\t\tdisable_session_recording?: boolean;\n\n\t\t/**\n\t\t * Autocapture settings\n\t\t */\n\t\tautocapture?: boolean;\n\n\t\t/**\n\t\t * Capture pageviews automatically\n\t\t */\n\t\tcapture_pageview?: boolean;\n\n\t\t/**\n\t\t * Capture pageleave events\n\t\t */\n\t\tcapture_pageleave?: boolean;\n\n\t\t/**\n\t\t * Cross-subdomain cookie\n\t\t */\n\t\tcross_subdomain_cookie?: boolean;\n\n\t\t/**\n\t\t * Advanced feature flags support\n\t\t */\n\t\tadvanced_disable_feature_flags?: boolean;\n\n\t\t/**\n\t\t * Other PostHog options\n\t\t */\n\t\t[key: string]: unknown;\n\t};\n};\n\n/**\n * Analytics instance interface\n */\nexport type Analytics = {\n\t/**\n\t * Track a custom event\n\t */\n\ttrackEvent: (eventType: EventType | string, properties?: EventProperties) => void;\n\n\t/**\n\t * Track an error with full stack trace\n\t */\n\ttrackError: (error: Error, additionalProperties?: EventProperties) => void;\n\n\t/**\n\t * Check if a feature flag is enabled\n\t */\n\tisFeatureEnabled: (flagKey: string) => boolean | undefined;\n\n\t/**\n\t * Get the value of a feature flag\n\t */\n\tgetFeatureFlag: (flagKey: string) => string | boolean | undefined;\n\n\t/**\n\t * Reload feature flags from PostHog\n\t */\n\treloadFeatureFlags: () => void;\n\n\t/**\n\t * Identify a user (optional - for advanced use cases)\n\t * Note: By default we only track installations, not users\n\t */\n\tidentify: (distinctId: string, properties?: Record<string, unknown>) => void;\n\n\t/**\n\t * Reset the user identity\n\t */\n\treset: () => void;\n\n\t/**\n\t * Check if analytics is enabled\n\t */\n\tisEnabled: () => boolean;\n\n\t/**\n\t * Get the installation ID\n\t */\n\tgetInstallationId: () => string;\n};\n"],"mappings":"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","names":[]}
package/dist/server.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { A as AnalyticsConfig, a as Analytics } from './types-Ymgjicqi.js';
1
+ import { A as AnalyticsConfig, a as Analytics } from './types-DK5BiTnW.js';
2
2
  import 'zod';
3
3
 
4
4
  /**
@@ -1,4 +1,4 @@
1
- import z from 'zod';
1
+ import { z } from 'zod';
2
2
 
3
3
  /**
4
4
  * Event types supported by the analytics system.
@@ -35,7 +35,7 @@ type ErrorProperties = z.infer<typeof ErrorPropertiesSchema>;
35
35
  * reverse proxy at ph-relay.networkcanvas.com. All authentication is handled
36
36
  * by the worker, so the API key is optional.
37
37
  */
38
- interface AnalyticsConfig {
38
+ type AnalyticsConfig = {
39
39
  /**
40
40
  * PostHog API host - should point to the Cloudflare Worker reverse proxy
41
41
  * Defaults to "https://ph-relay.networkcanvas.com"
@@ -98,11 +98,11 @@ interface AnalyticsConfig {
98
98
  */
99
99
  [key: string]: unknown;
100
100
  };
101
- }
101
+ };
102
102
  /**
103
103
  * Analytics instance interface
104
104
  */
105
- interface Analytics {
105
+ type Analytics = {
106
106
  /**
107
107
  * Track a custom event
108
108
  */
@@ -140,6 +140,6 @@ interface Analytics {
140
140
  * Get the installation ID
141
141
  */
142
142
  getInstallationId: () => string;
143
- }
143
+ };
144
144
 
145
145
  export { type AnalyticsConfig as A, type ErrorProperties as E, type Analytics as a, type EventProperties as b, type EventType as c, eventTypes as e, legacyEventTypeMap as l };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@codaco/analytics",
3
- "version": "9.0.0",
3
+ "version": "9.0.1",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -20,20 +20,20 @@
20
20
  "tag": "alpha"
21
21
  },
22
22
  "peerDependencies": {
23
- "next": "^16.0.3",
23
+ "next": "^16.0.7",
24
24
  "react": "^19.2.0"
25
25
  },
26
26
  "devDependencies": {
27
- "@types/node": "^22.18.8",
28
- "@types/react": "^19.2.5",
27
+ "@types/node": "^24.10.1",
28
+ "@types/react": "^19.2.7",
29
29
  "tsup": "^8.5.1",
30
30
  "typescript": "^5.9.3",
31
- "vitest": "^4.0.9",
31
+ "vitest": "^4.0.13",
32
32
  "@codaco/tsconfig": "0.1.0"
33
33
  },
34
34
  "dependencies": {
35
- "posthog-js": "^1.214.4",
36
- "zod": "^4.1.12"
35
+ "posthog-js": "^1.304.0",
36
+ "zod": "^4.1.13"
37
37
  },
38
38
  "scripts": {
39
39
  "build": "tsup src/index.ts src/server.ts --format esm --dts --clean --sourcemap",
package/src/provider.tsx CHANGED
@@ -13,10 +13,10 @@ export const AnalyticsContext = createContext<Analytics | null>(null);
13
13
  /**
14
14
  * Props for the AnalyticsProvider
15
15
  */
16
- export interface AnalyticsProviderProps {
16
+ export type AnalyticsProviderProps = {
17
17
  children: ReactNode;
18
18
  config: AnalyticsConfig;
19
- }
19
+ };
20
20
 
21
21
  /**
22
22
  * Provider component that initializes PostHog and provides analytics context
package/src/types.ts CHANGED
@@ -1,4 +1,4 @@
1
- import z from "zod";
1
+ import { z } from "zod";
2
2
 
3
3
  /**
4
4
  * Event types supported by the analytics system.
@@ -55,7 +55,7 @@ export type ErrorProperties = z.infer<typeof ErrorPropertiesSchema>;
55
55
  * reverse proxy at ph-relay.networkcanvas.com. All authentication is handled
56
56
  * by the worker, so the API key is optional.
57
57
  */
58
- export interface AnalyticsConfig {
58
+ export type AnalyticsConfig = {
59
59
  /**
60
60
  * PostHog API host - should point to the Cloudflare Worker reverse proxy
61
61
  * Defaults to "https://ph-relay.networkcanvas.com"
@@ -129,12 +129,12 @@ export interface AnalyticsConfig {
129
129
  */
130
130
  [key: string]: unknown;
131
131
  };
132
- }
132
+ };
133
133
 
134
134
  /**
135
135
  * Analytics instance interface
136
136
  */
137
- export interface Analytics {
137
+ export type Analytics = {
138
138
  /**
139
139
  * Track a custom event
140
140
  */
@@ -180,4 +180,4 @@ export interface Analytics {
180
180
  * Get the installation ID
181
181
  */
182
182
  getInstallationId: () => string;
183
- }
183
+ };
package/tsconfig.json CHANGED
@@ -4,6 +4,6 @@
4
4
  "baseUrl": ".",
5
5
  "tsBuildInfoFile": "node_modules/.cache/tsbuildinfo.json"
6
6
  },
7
- "include": ["."],
7
+ "include": ["src"],
8
8
  "exclude": ["dist", "build", "node_modules"]
9
9
  }