@heycatch/sdk 0.8.3 → 0.8.5-dev.2545

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 CHANGED
@@ -5,6 +5,33 @@ The official [HeyCatch](https://heycatch.ai) package for your app.
5
5
  _(AI Agents: the setup guide is https://heycatch.ai/agents.md - you also need
6
6
  the project key from the user's HeyCatch dashboard Install page.)_
7
7
 
8
+ ## Sign-in and sign-out
9
+
10
+ Call `setIdentity` right after sign-in and `resetIdentity` on sign-out:
11
+
12
+ ```ts
13
+ // After sign-in. A stable internal user id - never an email or a session
14
+ // token. Email and name, if you send them, go in the properties.
15
+ analytics.setIdentity(user.id, { email: user.email, name: user.name });
16
+
17
+ analytics.resetIdentity(); // on sign-out, so the next person starts anonymous
18
+ ```
19
+
20
+ Skip `resetIdentity` and the device keeps the signed-out user's identity.
21
+ Everything the next person does before signing in is recorded as the
22
+ previous user. On a shared device - a work tablet, a kiosk, a family
23
+ computer - whoever uses it without signing in lands in the last signed-in
24
+ user's profile, which then describes several people. HeyCatch's per-user summaries and recommendations are written from
25
+ those profiles, so they end up describing someone who does not exist.
26
+
27
+ `setIdentity` with a different user than the one already signed in resets
28
+ on its own, so a direct account switch is safe. What it cannot know is that
29
+ someone signed out and left: only your sign-out handler knows that.
30
+
31
+ `resetIdentity` works in the browser and in React Native. On the server it
32
+ is a no-op, so isomorphic sign-out code still resolves there - but the call
33
+ has to run on the device to take effect.
34
+
8
35
  ## Privacy & consent options
9
36
 
10
37
  `init()` accepts optional privacy/consent options alongside `projectKey`. Every
@@ -24,6 +51,7 @@ analytics.init({
24
51
  cookieExpirationDays: 365, // days before the persistence cookie expires
25
52
  optOutCapturingByDefault: true, // start with capturing off - see below
26
53
  respectDnt: true, // honor the browser's Do Not Track signal
54
+ collectIp: false, // don't store the visitor's IP address or their location - see below
27
55
  });
28
56
  ```
29
57
 
@@ -46,6 +74,54 @@ it was. This is always on, has no option, and runs after your `beforeSend`,
46
74
  so a hook cannot put a token back. It applies in the browser, in React
47
75
  Native, and on the server alike.
48
76
 
77
+ ### Visitor IP addresses
78
+
79
+ Set `collectIp: false` and no event stores the visitor's IP address, and no
80
+ country or city is derived from it. The address does not reach analytics
81
+ storage at all: the SDK blanks it on every event, after your `beforeSend`,
82
+ and HeyCatch's ingest drops it from the request too.
83
+
84
+ It is decided per visitor, so if your banner asks about IP or location you
85
+ can pass that answer straight through, and flip it when the visitor answers
86
+ later:
87
+
88
+ ```ts
89
+ // `=== true`: a visitor who has not answered yet is not collected either
90
+ analytics.init({
91
+ projectKey: 'hck_pk_...',
92
+ collectIp: storedIpAnswer() === true,
93
+ });
94
+
95
+ // in your consent banner's handler
96
+ analytics.setIpCollection(allowsIp); // false stops collecting from the next event
97
+ ```
98
+
99
+ Nothing is remembered between page loads or app launches: pass the
100
+ visitor's answer to `init()` every time. `setIpCollection()` before
101
+ `init()` logs a warning and does nothing. Unset, or `true`, collects the
102
+ IP as before. What `false` costs, and what it
103
+ does not promise:
104
+
105
+ - No country in your users table for new visitors, and no geo breakdowns
106
+ for those events. A returning visitor keeps the country already stored on
107
+ their profile from before.
108
+ - It applies from the SDK version that has it. A mobile app needs a new
109
+ release, and app versions already on users' phones keep sending IPs.
110
+ - It has to be set on every surface you ship - your site and your app each
111
+ have their own `init()`. One left out keeps sending IPs for that surface.
112
+ - What you can tell your users is "we don't store your IP address or a
113
+ location derived from it" - for what they do after you turn it off; a
114
+ country already on a returning visitor's profile stays, and location you
115
+ send yourself in event or person properties is stored as you sent it.
116
+ Not "your analytics is anonymous":
117
+ the device id, and your own user id after `setIdentity`, stay on events.
118
+ If your banner asks for consent to analytics as a whole, that is the
119
+ [consent gate](#consent-gate) below, not this switch.
120
+
121
+ It works in the browser and in React Native. The server entry accepts
122
+ `collectIp` and `setIpCollection()` and ignores both: a server event's
123
+ request comes from your server, not a visitor.
124
+
49
125
  ### Consent gate
50
126
 
51
127
  Set `optOutCapturingByDefault: true` to capture nothing until your visitor
@@ -59,6 +135,14 @@ analytics.optOutCapturing(); // consent withdrawn - stop again
59
135
  While the gate is closed nothing is written to browser storage either, so no
60
136
  identifier lands before consent - not just "no events sent".
61
137
 
138
+ A visitor who arrives through one of your HeyCatch short links lands on a URL
139
+ carrying `?utm_source=heycatch&utm_campaign=<letter>`. The SDK removes those
140
+ from the address bar a second after the first capture has read them - and
141
+ behind the gate, that first capture is the one `optInCapturing()` makes, so
142
+ the URL stays as it is until then and the visit is still attributed after
143
+ consent. Your own UTM links (any `utm_source` other than `heycatch`) are never
144
+ touched.
145
+
62
146
  Call `init()` before either one. Neither is remembered if it runs first -
63
147
  there is no transport yet to carry the decision - and both warn on the
64
148
  console when that happens rather than failing quietly. `init()`'s own config
@@ -72,8 +156,8 @@ to consent for - each one already names its `userId` and only happens
72
156
  because your code called it.
73
157
 
74
158
  The remaining options above are browser behaviour. React Native honours
75
- `optOutCapturingByDefault`; the rest describe a DOM and a browser store it
76
- does not have. The server entry accepts the same `HeyCatchConfig` so one
159
+ `optOutCapturingByDefault` and `collectIp`; the rest describe a DOM and a
160
+ browser store it does not have. The server entry accepts the same `HeyCatchConfig` so one
77
161
  object works under every import condition, and ignores them.
78
162
 
79
163
  ## Delivery options