@walkeros/web-destination-hotjar 3.4.0-next-1776749829492

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/README.md ADDED
@@ -0,0 +1,172 @@
1
+ <p align="left">
2
+ <a href="https://www.walkeros.io">
3
+ <img alt="walkerOS" title="walkerOS" src="https://www.walkeros.io/img/walkerOS_logo.svg" width="256px"/>
4
+ </a>
5
+ </p>
6
+
7
+ # Hotjar Destination for walkerOS
8
+
9
+ [Source Code](https://github.com/elbwalker/walkerOS/tree/main/packages/web/destinations/hotjar)
10
+ &bull;
11
+ [NPM Package](https://www.npmjs.com/package/@walkeros/web-destination-hotjar)
12
+ &bull; [Documentation](https://www.walkeros.io/docs/destinations/web/hotjar)
13
+
14
+ This package forwards walkerOS events to [Hotjar](https://www.hotjar.com/) —
15
+ session recordings, heatmaps, surveys, and on-page feedback. Built on the
16
+ official [`@hotjar/browser`](https://www.npmjs.com/package/@hotjar/browser) SDK.
17
+
18
+ walkerOS follows a **source → collector → destination** architecture. This
19
+ Hotjar destination receives processed events from the walkerOS collector and
20
+ forwards them as Hotjar events, identities, and SPA route notifications.
21
+
22
+ ## Features
23
+
24
+ - **Default event forwarding** — every walkerOS event becomes
25
+ `Hotjar.event(name)` with no additional config
26
+ - **Identity** — `Hotjar.identify(userId, attributes)` with userId extracted
27
+ from the resolved mapping value; remaining keys become user attributes
28
+ - **SPA state change** — `Hotjar.stateChange(path)` for accurate heatmaps on
29
+ virtual page views in single-page applications
30
+ - **Snippet injection** — `@hotjar/browser` handles script loading, including
31
+ CSP `nonce` and debug mode
32
+
33
+ ## Installation
34
+
35
+ ```sh
36
+ npm install @walkeros/web-destination-hotjar
37
+ ```
38
+
39
+ ## Quick Start
40
+
41
+ ```typescript
42
+ import { startFlow } from '@walkeros/collector';
43
+ import { destinationHotjar } from '@walkeros/web-destination-hotjar';
44
+
45
+ await startFlow({
46
+ destinations: {
47
+ hotjar: {
48
+ code: destinationHotjar,
49
+ config: {
50
+ settings: {
51
+ siteId: 1234567, // your Hotjar site ID
52
+ },
53
+ },
54
+ },
55
+ },
56
+ });
57
+ ```
58
+
59
+ ## Configuration
60
+
61
+ ### Settings (destination-level)
62
+
63
+ | Name | Type | Description | Required |
64
+ | --------------- | --------------- | ------------------------------------------------------------------------------------------------------ | -------- |
65
+ | `siteId` | `number` | Hotjar site ID (numeric, from dashboard Settings) | Yes |
66
+ | `hotjarVersion` | `number` | Hotjar snippet version. Defaults to `6`. Override only if Hotjar releases a new version. | No |
67
+ | `debug` | `boolean` | Enable Hotjar debug mode for development troubleshooting | No |
68
+ | `nonce` | `string` | CSP nonce for the injected Hotjar script tag (required with strict Content-Security-Policy) | No |
69
+ | `identify` | `Mapping.Value` | Destination-level identity mapping; resolves to `{ userId, ...attributes }` for `Hotjar.identify(...)` | No |
70
+
71
+ ### Mapping (`rule.settings`)
72
+
73
+ | Name | Type | Description |
74
+ | ------------- | --------------- | ------------------------------------------------------------------------------------------------------------ |
75
+ | `identify` | `Mapping.Value` | Per-event identity override; resolves to `{ userId, ...attributes }` → `Hotjar.identify(userId, attributes)` |
76
+ | `stateChange` | `Mapping.Value` | SPA route change; resolves to a relative path string → `Hotjar.stateChange(path)` |
77
+
78
+ Standard mapping features also apply:
79
+
80
+ - `name` — rename the forwarded event (`Hotjar.event(<new name>)`)
81
+ - `skip` — suppress the default `Hotjar.event(...)` call while still running
82
+ `identify` / `stateChange`
83
+ - `ignore` — drop the event entirely (no calls produced)
84
+
85
+ ## Event Forwarding
86
+
87
+ Hotjar's `event(actionName)` API is name-only — no properties, no payload. The
88
+ destination forwards the walkerOS `event.name` (e.g. `"order complete"`) by
89
+ default. Rename with `mapping.name`:
90
+
91
+ ```typescript
92
+ mapping: {
93
+ order: {
94
+ complete: {
95
+ name: 'completed_purchase',
96
+ },
97
+ },
98
+ }
99
+ ```
100
+
101
+ ## Identity
102
+
103
+ Hotjar recommends calling `identify()` on every page load so subsequent events
104
+ are associated with the right user. Configure at the destination level:
105
+
106
+ ```typescript
107
+ settings: {
108
+ siteId: 1234567,
109
+ identify: {
110
+ map: {
111
+ userId: 'user.id',
112
+ plan: 'user.plan',
113
+ },
114
+ },
115
+ }
116
+ ```
117
+
118
+ The resolved object's `userId` becomes the first positional argument; every
119
+ other key becomes a user attribute (Hotjar accepts `string | number | boolean`).
120
+ Non-primitive values are skipped.
121
+
122
+ Per-event identity overrides destination-level identity via
123
+ `mapping.settings.identify`.
124
+
125
+ ## SPA State Change
126
+
127
+ For single-page applications, fire `Hotjar.stateChange(path)` on route changes
128
+ so heatmaps aggregate by virtual URL. Typical pattern: hook into your router and
129
+ emit a walkerOS event:
130
+
131
+ ```typescript
132
+ mapping: {
133
+ page: {
134
+ view: {
135
+ skip: true, // Suppress default Hotjar.event('page view')
136
+ settings: {
137
+ stateChange: 'data.id', // Resolves to the new path
138
+ },
139
+ },
140
+ },
141
+ }
142
+ ```
143
+
144
+ ## Consent
145
+
146
+ Hotjar has no runtime consent API. Consent is gated at the walkerOS level via
147
+ `config.consent`:
148
+
149
+ ```typescript
150
+ destinations: {
151
+ hotjar: {
152
+ code: destinationHotjar,
153
+ config: {
154
+ consent: { marketing: true },
155
+ settings: { siteId: 1234567 },
156
+ },
157
+ },
158
+ }
159
+ ```
160
+
161
+ Unconsented events are blocked by the collector before reaching the destination.
162
+
163
+ ## Contribute
164
+
165
+ Feel free to contribute by submitting an
166
+ [issue](https://github.com/elbwalker/walkerOS/issues), starting a
167
+ [discussion](https://github.com/elbwalker/walkerOS/discussions), or getting in
168
+ [contact](https://calendly.com/elb-alexander/30min).
169
+
170
+ ## License
171
+
172
+ This project is licensed under the MIT License.
package/dist/dev.d.mts ADDED
@@ -0,0 +1,157 @@
1
+ import * as _walkeros_core_dev from '@walkeros/core/dev';
2
+ import { z } from '@walkeros/core/dev';
3
+ import { Mapping as Mapping$1, Flow } from '@walkeros/core';
4
+ import { DestinationWeb } from '@walkeros/web-core';
5
+
6
+ declare const SettingsSchema: z.ZodObject<{
7
+ siteId: z.ZodNumber;
8
+ hotjarVersion: z.ZodOptional<z.ZodNumber>;
9
+ debug: z.ZodOptional<z.ZodBoolean>;
10
+ nonce: z.ZodOptional<z.ZodString>;
11
+ identify: z.ZodOptional<z.ZodUnknown>;
12
+ }, z.core.$strip>;
13
+ type Settings$1 = z.infer<typeof SettingsSchema>;
14
+
15
+ declare const MappingSchema: z.ZodObject<{
16
+ identify: z.ZodOptional<z.ZodUnknown>;
17
+ stateChange: z.ZodOptional<z.ZodUnknown>;
18
+ }, z.core.$strip>;
19
+ type Mapping = z.infer<typeof MappingSchema>;
20
+
21
+ declare const settings: _walkeros_core_dev.JSONSchema;
22
+ declare const mapping: _walkeros_core_dev.JSONSchema;
23
+
24
+ type index$1_Mapping = Mapping;
25
+ declare const index$1_MappingSchema: typeof MappingSchema;
26
+ declare const index$1_SettingsSchema: typeof SettingsSchema;
27
+ declare const index$1_mapping: typeof mapping;
28
+ declare const index$1_settings: typeof settings;
29
+ declare namespace index$1 {
30
+ export { type index$1_Mapping as Mapping, index$1_MappingSchema as MappingSchema, type Settings$1 as Settings, index$1_SettingsSchema as SettingsSchema, index$1_mapping as mapping, index$1_settings as settings };
31
+ }
32
+
33
+ /**
34
+ * Settings (destination-level).
35
+ *
36
+ * siteId is the numeric Hotjar site ID from the dashboard.
37
+ * identify resolves to { userId, ...attributes } for Hotjar.identify().
38
+ */
39
+ interface Settings {
40
+ siteId: number;
41
+ hotjarVersion?: number;
42
+ debug?: boolean;
43
+ nonce?: string;
44
+ identify?: Mapping$1.Value;
45
+ }
46
+ /**
47
+ * Hotjar SDK surface -- the subset of @hotjar/browser methods this
48
+ * destination uses. Mirrors the default export so tests can mock
49
+ * each method individually.
50
+ */
51
+ interface HotjarSDK {
52
+ init: (hotjarId: number, hotjarVersion: number, opts?: {
53
+ debug?: boolean;
54
+ nonce?: string;
55
+ }) => boolean;
56
+ event: (actionName: string) => boolean;
57
+ identify: (userId: string | null, userInfo: Record<string, string | number | Date | boolean>) => boolean;
58
+ stateChange: (relativePath: string) => boolean;
59
+ isReady: () => boolean;
60
+ }
61
+ /**
62
+ * Env -- optional override for the vendor SDK. Production leaves this
63
+ * undefined and the destination falls back to the real @hotjar/browser
64
+ * default export. Tests provide a mock via env.hotjar = { ... }.
65
+ */
66
+ interface Env extends DestinationWeb.Env {
67
+ hotjar?: HotjarSDK;
68
+ }
69
+
70
+ /**
71
+ * Pre-init environment -- Hotjar SDK methods are no-ops until init wires them.
72
+ */
73
+ declare const init: Env | undefined;
74
+ /**
75
+ * Post-init environment -- Hotjar SDK methods are spy-able no-ops.
76
+ * Tests clone this and replace individual methods with jest.fn() for assertions.
77
+ */
78
+ declare const push: Env;
79
+ /**
80
+ * Simulation tracking paths for CLI --simulate
81
+ */
82
+ declare const simulation: string[];
83
+
84
+ declare const env_init: typeof init;
85
+ declare const env_push: typeof push;
86
+ declare const env_simulation: typeof simulation;
87
+ declare namespace env {
88
+ export { env_init as init, env_push as push, env_simulation as simulation };
89
+ }
90
+
91
+ /**
92
+ * Extended step example allowing destination-level settings overrides.
93
+ */
94
+ type HotjarStepExample = Flow.StepExample & {
95
+ settings?: Partial<Settings>;
96
+ };
97
+ /**
98
+ * Default event forwarding -- every walkerOS event becomes Hotjar.event(name).
99
+ * No mapping rule; the destination's default push behavior fires.
100
+ */
101
+ declare const defaultEventForwarding: HotjarStepExample;
102
+ /**
103
+ * Wildcard ignore pattern -- suppresses noisy events.
104
+ * The destination must produce zero calls.
105
+ */
106
+ declare const wildcardIgnored: HotjarStepExample;
107
+ /**
108
+ * Renamed event via mapping.name -- order complete becomes completed_purchase.
109
+ */
110
+ declare const renamedEvent: HotjarStepExample;
111
+ /**
112
+ * Per-event identity via mapping.settings.identify.
113
+ * Resolves { userId, ...attributes } -> Hotjar.identify(userId, attributes).
114
+ * Identify fires before event per Hotjar's guidance.
115
+ */
116
+ declare const userLoginIdentify: HotjarStepExample;
117
+ /**
118
+ * Destination-level settings.identify -- fires on every push.
119
+ * Hotjar recommends calling identify() on every page load.
120
+ */
121
+ declare const destinationLevelIdentify: HotjarStepExample;
122
+ /**
123
+ * SPA state change -- stateChange mapping resolves to path string.
124
+ * skip=true suppresses the default Hotjar.event() call.
125
+ */
126
+ declare const pageViewStateChange: HotjarStepExample;
127
+ /**
128
+ * Combined features -- identify + renamed event on the same push.
129
+ * Execution order: identify -> event.
130
+ */
131
+ declare const combinedFeatures: HotjarStepExample;
132
+ /**
133
+ * mapping.skip -- suppresses the default Hotjar.event() call. No other
134
+ * settings active, so the destination produces zero calls.
135
+ */
136
+ declare const pageViewSkip: HotjarStepExample;
137
+
138
+ type step_HotjarStepExample = HotjarStepExample;
139
+ declare const step_combinedFeatures: typeof combinedFeatures;
140
+ declare const step_defaultEventForwarding: typeof defaultEventForwarding;
141
+ declare const step_destinationLevelIdentify: typeof destinationLevelIdentify;
142
+ declare const step_pageViewSkip: typeof pageViewSkip;
143
+ declare const step_pageViewStateChange: typeof pageViewStateChange;
144
+ declare const step_renamedEvent: typeof renamedEvent;
145
+ declare const step_userLoginIdentify: typeof userLoginIdentify;
146
+ declare const step_wildcardIgnored: typeof wildcardIgnored;
147
+ declare namespace step {
148
+ export { type step_HotjarStepExample as HotjarStepExample, step_combinedFeatures as combinedFeatures, step_defaultEventForwarding as defaultEventForwarding, step_destinationLevelIdentify as destinationLevelIdentify, step_pageViewSkip as pageViewSkip, step_pageViewStateChange as pageViewStateChange, step_renamedEvent as renamedEvent, step_userLoginIdentify as userLoginIdentify, step_wildcardIgnored as wildcardIgnored };
149
+ }
150
+
151
+ declare const index_env: typeof env;
152
+ declare const index_step: typeof step;
153
+ declare namespace index {
154
+ export { index_env as env, index_step as step };
155
+ }
156
+
157
+ export { index as examples, index$1 as schemas };
package/dist/dev.d.ts ADDED
@@ -0,0 +1,157 @@
1
+ import * as _walkeros_core_dev from '@walkeros/core/dev';
2
+ import { z } from '@walkeros/core/dev';
3
+ import { Mapping as Mapping$1, Flow } from '@walkeros/core';
4
+ import { DestinationWeb } from '@walkeros/web-core';
5
+
6
+ declare const SettingsSchema: z.ZodObject<{
7
+ siteId: z.ZodNumber;
8
+ hotjarVersion: z.ZodOptional<z.ZodNumber>;
9
+ debug: z.ZodOptional<z.ZodBoolean>;
10
+ nonce: z.ZodOptional<z.ZodString>;
11
+ identify: z.ZodOptional<z.ZodUnknown>;
12
+ }, z.core.$strip>;
13
+ type Settings$1 = z.infer<typeof SettingsSchema>;
14
+
15
+ declare const MappingSchema: z.ZodObject<{
16
+ identify: z.ZodOptional<z.ZodUnknown>;
17
+ stateChange: z.ZodOptional<z.ZodUnknown>;
18
+ }, z.core.$strip>;
19
+ type Mapping = z.infer<typeof MappingSchema>;
20
+
21
+ declare const settings: _walkeros_core_dev.JSONSchema;
22
+ declare const mapping: _walkeros_core_dev.JSONSchema;
23
+
24
+ type index$1_Mapping = Mapping;
25
+ declare const index$1_MappingSchema: typeof MappingSchema;
26
+ declare const index$1_SettingsSchema: typeof SettingsSchema;
27
+ declare const index$1_mapping: typeof mapping;
28
+ declare const index$1_settings: typeof settings;
29
+ declare namespace index$1 {
30
+ export { type index$1_Mapping as Mapping, index$1_MappingSchema as MappingSchema, type Settings$1 as Settings, index$1_SettingsSchema as SettingsSchema, index$1_mapping as mapping, index$1_settings as settings };
31
+ }
32
+
33
+ /**
34
+ * Settings (destination-level).
35
+ *
36
+ * siteId is the numeric Hotjar site ID from the dashboard.
37
+ * identify resolves to { userId, ...attributes } for Hotjar.identify().
38
+ */
39
+ interface Settings {
40
+ siteId: number;
41
+ hotjarVersion?: number;
42
+ debug?: boolean;
43
+ nonce?: string;
44
+ identify?: Mapping$1.Value;
45
+ }
46
+ /**
47
+ * Hotjar SDK surface -- the subset of @hotjar/browser methods this
48
+ * destination uses. Mirrors the default export so tests can mock
49
+ * each method individually.
50
+ */
51
+ interface HotjarSDK {
52
+ init: (hotjarId: number, hotjarVersion: number, opts?: {
53
+ debug?: boolean;
54
+ nonce?: string;
55
+ }) => boolean;
56
+ event: (actionName: string) => boolean;
57
+ identify: (userId: string | null, userInfo: Record<string, string | number | Date | boolean>) => boolean;
58
+ stateChange: (relativePath: string) => boolean;
59
+ isReady: () => boolean;
60
+ }
61
+ /**
62
+ * Env -- optional override for the vendor SDK. Production leaves this
63
+ * undefined and the destination falls back to the real @hotjar/browser
64
+ * default export. Tests provide a mock via env.hotjar = { ... }.
65
+ */
66
+ interface Env extends DestinationWeb.Env {
67
+ hotjar?: HotjarSDK;
68
+ }
69
+
70
+ /**
71
+ * Pre-init environment -- Hotjar SDK methods are no-ops until init wires them.
72
+ */
73
+ declare const init: Env | undefined;
74
+ /**
75
+ * Post-init environment -- Hotjar SDK methods are spy-able no-ops.
76
+ * Tests clone this and replace individual methods with jest.fn() for assertions.
77
+ */
78
+ declare const push: Env;
79
+ /**
80
+ * Simulation tracking paths for CLI --simulate
81
+ */
82
+ declare const simulation: string[];
83
+
84
+ declare const env_init: typeof init;
85
+ declare const env_push: typeof push;
86
+ declare const env_simulation: typeof simulation;
87
+ declare namespace env {
88
+ export { env_init as init, env_push as push, env_simulation as simulation };
89
+ }
90
+
91
+ /**
92
+ * Extended step example allowing destination-level settings overrides.
93
+ */
94
+ type HotjarStepExample = Flow.StepExample & {
95
+ settings?: Partial<Settings>;
96
+ };
97
+ /**
98
+ * Default event forwarding -- every walkerOS event becomes Hotjar.event(name).
99
+ * No mapping rule; the destination's default push behavior fires.
100
+ */
101
+ declare const defaultEventForwarding: HotjarStepExample;
102
+ /**
103
+ * Wildcard ignore pattern -- suppresses noisy events.
104
+ * The destination must produce zero calls.
105
+ */
106
+ declare const wildcardIgnored: HotjarStepExample;
107
+ /**
108
+ * Renamed event via mapping.name -- order complete becomes completed_purchase.
109
+ */
110
+ declare const renamedEvent: HotjarStepExample;
111
+ /**
112
+ * Per-event identity via mapping.settings.identify.
113
+ * Resolves { userId, ...attributes } -> Hotjar.identify(userId, attributes).
114
+ * Identify fires before event per Hotjar's guidance.
115
+ */
116
+ declare const userLoginIdentify: HotjarStepExample;
117
+ /**
118
+ * Destination-level settings.identify -- fires on every push.
119
+ * Hotjar recommends calling identify() on every page load.
120
+ */
121
+ declare const destinationLevelIdentify: HotjarStepExample;
122
+ /**
123
+ * SPA state change -- stateChange mapping resolves to path string.
124
+ * skip=true suppresses the default Hotjar.event() call.
125
+ */
126
+ declare const pageViewStateChange: HotjarStepExample;
127
+ /**
128
+ * Combined features -- identify + renamed event on the same push.
129
+ * Execution order: identify -> event.
130
+ */
131
+ declare const combinedFeatures: HotjarStepExample;
132
+ /**
133
+ * mapping.skip -- suppresses the default Hotjar.event() call. No other
134
+ * settings active, so the destination produces zero calls.
135
+ */
136
+ declare const pageViewSkip: HotjarStepExample;
137
+
138
+ type step_HotjarStepExample = HotjarStepExample;
139
+ declare const step_combinedFeatures: typeof combinedFeatures;
140
+ declare const step_defaultEventForwarding: typeof defaultEventForwarding;
141
+ declare const step_destinationLevelIdentify: typeof destinationLevelIdentify;
142
+ declare const step_pageViewSkip: typeof pageViewSkip;
143
+ declare const step_pageViewStateChange: typeof pageViewStateChange;
144
+ declare const step_renamedEvent: typeof renamedEvent;
145
+ declare const step_userLoginIdentify: typeof userLoginIdentify;
146
+ declare const step_wildcardIgnored: typeof wildcardIgnored;
147
+ declare namespace step {
148
+ export { type step_HotjarStepExample as HotjarStepExample, step_combinedFeatures as combinedFeatures, step_defaultEventForwarding as defaultEventForwarding, step_destinationLevelIdentify as destinationLevelIdentify, step_pageViewSkip as pageViewSkip, step_pageViewStateChange as pageViewStateChange, step_renamedEvent as renamedEvent, step_userLoginIdentify as userLoginIdentify, step_wildcardIgnored as wildcardIgnored };
149
+ }
150
+
151
+ declare const index_env: typeof env;
152
+ declare const index_step: typeof step;
153
+ declare namespace index {
154
+ export { index_env as env, index_step as step };
155
+ }
156
+
157
+ export { index as examples, index$1 as schemas };