@zoho_apptics/apptics-js-sdk 2.0.0-beta.1 → 2.0.0-beta.2

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 (183) hide show
  1. package/CHANGELOG.md +80 -16
  2. package/README.md +187 -100
  3. package/dist/apptics.esm.min.js +2 -2
  4. package/dist/apptics.esm.min.js.map +1 -1
  5. package/dist/apptics.min.js +2 -2
  6. package/dist/apptics.min.js.map +1 -1
  7. package/dist/chunks/lifecycle-C6m1W7jo.min.js +3 -0
  8. package/dist/chunks/lifecycle-C6m1W7jo.min.js.map +1 -0
  9. package/dist/chunks/send-CgUO82ne.min.js +3 -0
  10. package/dist/chunks/send-CgUO82ne.min.js.map +1 -0
  11. package/dist/cjs/core/attempts.js +1 -1
  12. package/dist/cjs/core/batch.js +1 -2
  13. package/dist/cjs/core/consent.d.ts +13 -3
  14. package/dist/cjs/core/consent.js +24 -10
  15. package/dist/cjs/core/constants.d.ts +22 -17
  16. package/dist/cjs/core/constants.js +22 -19
  17. package/dist/cjs/core/db.js +1 -1
  18. package/dist/cjs/core/debug.js +1 -1
  19. package/dist/cjs/core/env.d.ts +0 -3
  20. package/dist/cjs/core/env.js +1 -9
  21. package/dist/cjs/core/framework-id.d.ts +1 -1
  22. package/dist/cjs/core/framework-id.js +3 -3
  23. package/dist/cjs/core/guard.js +1 -1
  24. package/dist/cjs/core/hooks.d.ts +5 -0
  25. package/dist/cjs/core/hooks.js +2 -1
  26. package/dist/cjs/core/locks.js +1 -1
  27. package/dist/cjs/core/logger.js +1 -1
  28. package/dist/cjs/core/state.d.ts +6 -4
  29. package/dist/cjs/core/state.js +2 -4
  30. package/dist/cjs/core/storage.js +1 -4
  31. package/dist/cjs/core/stylesheet.js +1 -1
  32. package/dist/cjs/core/transport.js +13 -16
  33. package/dist/cjs/core/utils.js +1 -1
  34. package/dist/cjs/core/validate.js +1 -1
  35. package/dist/cjs/device/appversion.d.ts +10 -1
  36. package/dist/cjs/device/appversion.js +26 -3
  37. package/dist/cjs/device/index.d.ts +17 -2
  38. package/dist/cjs/device/index.js +195 -27
  39. package/dist/cjs/engagement/api-rules.js +1 -1
  40. package/dist/cjs/engagement/auto-api.js +1 -1
  41. package/dist/cjs/engagement/auto-screen.js +1 -1
  42. package/dist/cjs/engagement/defined-events.js +1 -1
  43. package/dist/cjs/engagement/send.js +7 -3
  44. package/dist/cjs/engagement/session.d.ts +17 -0
  45. package/dist/cjs/engagement/session.js +95 -4
  46. package/dist/cjs/engagement/track.d.ts +4 -4
  47. package/dist/cjs/engagement/track.js +15 -12
  48. package/dist/cjs/errors/send.js +2 -2
  49. package/dist/cjs/errors/track.d.ts +2 -1
  50. package/dist/cjs/errors/track.js +6 -4
  51. package/dist/cjs/feedback/controls.d.ts +6 -0
  52. package/dist/cjs/feedback/controls.js +74 -25
  53. package/dist/cjs/feedback/index.js +1 -1
  54. package/dist/cjs/feedback/logs.d.ts +3 -6
  55. package/dist/cjs/feedback/logs.js +8 -18
  56. package/dist/cjs/feedback/quartz.js +1 -1
  57. package/dist/cjs/feedback/send.d.ts +2 -2
  58. package/dist/cjs/feedback/send.js +4 -27
  59. package/dist/cjs/feedback/styles.js +2 -2
  60. package/dist/cjs/feedback/template.d.ts +1 -1
  61. package/dist/cjs/feedback/template.js +9 -1
  62. package/dist/cjs/feedback/ui.d.ts +7 -0
  63. package/dist/cjs/feedback/ui.js +160 -25
  64. package/dist/cjs/heatmap/send.d.ts +2 -0
  65. package/dist/cjs/heatmap/send.js +3 -5
  66. package/dist/cjs/heatmap/track.js +1 -1
  67. package/dist/cjs/index.d.ts +1 -2
  68. package/dist/cjs/index.js +54 -17
  69. package/dist/cjs/lifecycle.d.ts +13 -2
  70. package/dist/cjs/lifecycle.js +122 -54
  71. package/dist/cjs/remoteconfig/country.js +1 -1
  72. package/dist/cjs/remoteconfig/custom.js +1 -1
  73. package/dist/cjs/remoteconfig/evaluate.js +1 -1
  74. package/dist/cjs/remoteconfig/fetch.d.ts +17 -10
  75. package/dist/cjs/remoteconfig/fetch.js +126 -31
  76. package/dist/cjs/remoteconfig/index.d.ts +13 -4
  77. package/dist/cjs/remoteconfig/index.js +36 -20
  78. package/dist/cjs/remoteconfig/store.d.ts +15 -7
  79. package/dist/cjs/remoteconfig/store.js +68 -35
  80. package/dist/cjs/remoteconfig/tz-countries.js +1 -1
  81. package/dist/cjs/{core → remotelog}/callsite.d.ts +5 -4
  82. package/dist/cjs/{core → remotelog}/callsite.js +6 -5
  83. package/dist/cjs/remotelog/gate.js +1 -1
  84. package/dist/cjs/remotelog/logger.js +2 -2
  85. package/dist/cjs/remotelog/send.js +2 -2
  86. package/dist/cjs/remotelogger/index.js +1 -1
  87. package/dist/cjs/scheduler.d.ts +3 -1
  88. package/dist/cjs/scheduler.js +24 -21
  89. package/dist/cjs/types.d.ts +61 -16
  90. package/dist/cjs/user/index.js +6 -2
  91. package/dist/esm/core/attempts.js +1 -1
  92. package/dist/esm/core/batch.js +1 -2
  93. package/dist/esm/core/consent.d.ts +13 -3
  94. package/dist/esm/core/consent.js +24 -11
  95. package/dist/esm/core/constants.d.ts +22 -17
  96. package/dist/esm/core/constants.js +22 -19
  97. package/dist/esm/core/db.js +1 -1
  98. package/dist/esm/core/debug.js +1 -1
  99. package/dist/esm/core/env.d.ts +0 -3
  100. package/dist/esm/core/env.js +2 -9
  101. package/dist/esm/core/framework-id.d.ts +1 -1
  102. package/dist/esm/core/framework-id.js +3 -3
  103. package/dist/esm/core/guard.js +1 -1
  104. package/dist/esm/core/hooks.d.ts +5 -0
  105. package/dist/esm/core/hooks.js +2 -1
  106. package/dist/esm/core/locks.js +1 -1
  107. package/dist/esm/core/logger.js +1 -1
  108. package/dist/esm/core/state.d.ts +6 -4
  109. package/dist/esm/core/state.js +2 -4
  110. package/dist/esm/core/storage.js +1 -4
  111. package/dist/esm/core/stylesheet.js +1 -1
  112. package/dist/esm/core/transport.js +13 -16
  113. package/dist/esm/core/utils.js +1 -1
  114. package/dist/esm/core/validate.js +1 -1
  115. package/dist/esm/device/appversion.d.ts +10 -1
  116. package/dist/esm/device/appversion.js +26 -4
  117. package/dist/esm/device/index.d.ts +17 -2
  118. package/dist/esm/device/index.js +195 -30
  119. package/dist/esm/engagement/api-rules.js +1 -1
  120. package/dist/esm/engagement/auto-api.js +1 -1
  121. package/dist/esm/engagement/auto-screen.js +1 -1
  122. package/dist/esm/engagement/defined-events.js +1 -1
  123. package/dist/esm/engagement/send.js +7 -3
  124. package/dist/esm/engagement/session.d.ts +17 -0
  125. package/dist/esm/engagement/session.js +93 -5
  126. package/dist/esm/engagement/track.d.ts +4 -4
  127. package/dist/esm/engagement/track.js +16 -13
  128. package/dist/esm/errors/send.js +2 -2
  129. package/dist/esm/errors/track.d.ts +2 -1
  130. package/dist/esm/errors/track.js +6 -4
  131. package/dist/esm/feedback/controls.d.ts +6 -0
  132. package/dist/esm/feedback/controls.js +74 -26
  133. package/dist/esm/feedback/index.js +1 -1
  134. package/dist/esm/feedback/logs.d.ts +3 -6
  135. package/dist/esm/feedback/logs.js +8 -18
  136. package/dist/esm/feedback/quartz.js +1 -1
  137. package/dist/esm/feedback/send.d.ts +2 -2
  138. package/dist/esm/feedback/send.js +6 -29
  139. package/dist/esm/feedback/styles.js +2 -2
  140. package/dist/esm/feedback/template.d.ts +1 -1
  141. package/dist/esm/feedback/template.js +9 -1
  142. package/dist/esm/feedback/ui.d.ts +7 -0
  143. package/dist/esm/feedback/ui.js +161 -26
  144. package/dist/esm/heatmap/send.d.ts +2 -0
  145. package/dist/esm/heatmap/send.js +3 -5
  146. package/dist/esm/heatmap/track.js +1 -1
  147. package/dist/esm/index.d.ts +1 -2
  148. package/dist/esm/index.js +57 -20
  149. package/dist/esm/lifecycle.d.ts +13 -2
  150. package/dist/esm/lifecycle.js +126 -60
  151. package/dist/esm/remoteconfig/country.js +1 -1
  152. package/dist/esm/remoteconfig/custom.js +1 -1
  153. package/dist/esm/remoteconfig/evaluate.js +1 -1
  154. package/dist/esm/remoteconfig/fetch.d.ts +17 -10
  155. package/dist/esm/remoteconfig/fetch.js +127 -32
  156. package/dist/esm/remoteconfig/index.d.ts +13 -4
  157. package/dist/esm/remoteconfig/index.js +36 -20
  158. package/dist/esm/remoteconfig/store.d.ts +15 -7
  159. package/dist/esm/remoteconfig/store.js +68 -36
  160. package/dist/esm/remoteconfig/tz-countries.js +1 -1
  161. package/dist/esm/{core → remotelog}/callsite.d.ts +5 -4
  162. package/dist/esm/{core → remotelog}/callsite.js +6 -5
  163. package/dist/esm/remotelog/gate.js +1 -1
  164. package/dist/esm/remotelog/logger.js +2 -2
  165. package/dist/esm/remotelog/send.js +2 -2
  166. package/dist/esm/remotelogger/index.js +1 -1
  167. package/dist/esm/scheduler.d.ts +3 -1
  168. package/dist/esm/scheduler.js +25 -23
  169. package/dist/esm/types.d.ts +61 -16
  170. package/dist/esm/user/index.js +7 -3
  171. package/dist/feedback.esm.min.js +2 -2
  172. package/dist/feedback.esm.min.js.map +1 -1
  173. package/dist/remoteconfig.esm.min.js +3 -0
  174. package/dist/remoteconfig.esm.min.js.map +1 -0
  175. package/dist/remotelogger.esm.min.js +3 -0
  176. package/dist/remotelogger.esm.min.js.map +1 -0
  177. package/package.json +3 -2
  178. package/dist/chunks/lifecycle-VYr43KcB.min.js +0 -3
  179. package/dist/chunks/lifecycle-VYr43KcB.min.js.map +0 -1
  180. package/dist/cjs/auto-init.d.ts +0 -8
  181. package/dist/cjs/auto-init.js +0 -32
  182. package/dist/esm/auto-init.d.ts +0 -8
  183. package/dist/esm/auto-init.js +0 -29
package/README.md CHANGED
@@ -12,10 +12,10 @@ The SDK is plain TypeScript with no framework dependency. It works with any bund
12
12
  ## Install Apptics
13
13
 
14
14
  ```bash
15
- npm install @zoho_apptics/apptics-js-sdk@2.0.0-beta.1
15
+ npm install @zoho_apptics/apptics-js-sdk@2.0.0-beta.2
16
16
  ```
17
17
 
18
- A plain `npm install @zoho_apptics/apptics-js-sdk` still installs 1.0.2, the current `latest`. Upgrading from 1.0.2? `Apptics.init()` takes different config now; see [Migrating from 1.0.2 to 2.0.0-beta.1](#migrating-from-102-to-200-beta1).
18
+ A plain `npm install @zoho_apptics/apptics-js-sdk` still installs 1.0.2, the current `latest`. Upgrading from 1.0.2? `Apptics.init()` takes different config now; see [Migrating from 1.0.2 to 2.0.0-beta.2](#migrating-from-102-to-200-beta2).
19
19
 
20
20
  ## Initialize Apptics
21
21
 
@@ -44,7 +44,7 @@ The config object is **required**, with `base_url`, `auth_key`, `app_domain` and
44
44
 
45
45
  `Apptics.init()` returns right away. The SDK finishes starting once its storage has loaded, usually within a few milliseconds. Calls you make before that are queued and run in order, so you don't have to wait. If you need to know when it's running, use `await Apptics.ready()`.
46
46
 
47
- Every call belongs to an object, named after its feature, so you import only the object and code reads much as it does on Android: `Apptics.init()`, `AppticsEvent.addEvent()`, `AppticsError.trackError()`, `AppticsFeedback.feedbackFormOpen()`. See [The API at a glance](#the-api-at-a-glance). CommonJS works too (`const { Apptics } = require('@zoho_apptics/apptics-js-sdk')`). Importing the SDK is safe during server-side rendering: nothing runs until `Apptics.init()` is called in the browser.
47
+ Every call belongs to an object, named after its feature, so you import only the object: `Apptics.init()`, `AppticsEvent.addEvent()`, `AppticsError.trackError()`, `AppticsFeedback.feedbackFormOpen()`. See [The API at a glance](#the-api-at-a-glance). CommonJS works too (`const { Apptics } = require('@zoho_apptics/apptics-js-sdk')`). Importing the SDK is safe during server-side rendering: nothing runs until `Apptics.init()` is called in the browser.
48
48
 
49
49
  ### With a `<script>` tag (CDN)
50
50
 
@@ -52,7 +52,7 @@ Load the browser build and call `Apptics.init()` after it. One `<script>` tag is
52
52
  form's styles are inside the build, so there is no stylesheet to add.
53
53
 
54
54
  ```html
55
- <script src="https://cdn.jsdelivr.net/npm/@zoho_apptics/apptics-js-sdk@2.0.0-beta.1/dist/apptics.min.js"></script>
55
+ <script src="https://static.zohocdn.com/apptics-js-sdk/2.0.0-beta.2/apptics.min.js"></script>
56
56
  <script>
57
57
  Apptics.init({
58
58
  base_url: 'YOUR_BASE_URL',
@@ -71,7 +71,7 @@ The build defines the same objects as globals (`Apptics`, `AppticsEvent`, `Appti
71
71
  or send something are ignored until `Apptics.init()` has run, and the first such call logs a console
72
72
  warning saying so.
73
73
 
74
- **Pin the version** (`@2.0.0-beta.1`) rather than a tag or range such as `@beta`, so a release can't change what your pages load. See [Loading from a CDN](#loading-from-a-cdn) for module builds, unpkg and subresource integrity.
74
+ Each release has its own folder on the CDN, `https://static.zohocdn.com/apptics-js-sdk/{version}/`, so a page keeps loading the version it names until you change it. See [Loading from a CDN](#loading-from-a-cdn) for module builds and subresource integrity.
75
75
 
76
76
  ### The API at a glance
77
77
 
@@ -80,22 +80,23 @@ Each feature's calls are on one object:
80
80
  | Object | Calls | Entry point |
81
81
  |---|---|---|
82
82
  | `Apptics` | `init(config)`, `ready()`, `flush()`, `reset()`, `enableDebug()`, `disableDebug()` | main |
83
- | `AppticsEvent` | `addEvent(eventName, groupName?, properties?)`, `addEvent(DefinedEvents.X, properties?)`, `DefinedEvents` | main |
84
- | `AppticsScreen` | `inScreen(screenName, properties?)` → id, `outScreen(id)` | main |
85
- | `AppticsError` | `trackError(error, properties?)`, `trackGlobalErrorHandler(enabled?)` | main |
83
+ | `AppticsEvent` | `addEvent(eventName, groupName, properties?)`, `addEvent(DefinedEvents.X, properties?)`, `setClickTracking(enabled?)`, `DefinedEvents` | main |
84
+ | `AppticsScreen` | `inScreen(screenName, properties?)` → id, `outScreen(id)`, `setScreenTracking(enabled?)` | main |
85
+ | `AppticsError` | `trackError(error, properties?)`, `setErrorTracking(enabled?)` | main |
86
86
  | `AppticsUser` | `setUser(userid, groupid?, properties?)`, `getUser()`, `UserBuilder` | main |
87
87
  | `AppticsSettings` | `setTrackingStatus(status)`, `getTrackingStatus()`, the `AP_TRACKING_STATUS` constants | main |
88
- | `AppticsApi` | `startTrackApi(url, method?)` → id, `endTrackApi(id, responseCode, responseMessage?)`, `configure(config)`, `enableApiTracking(enabled?)`, `ApiTrackingBuilder` | main |
89
- | `AppticsHeatmap` | `trackHeatmap(on?)` | main |
88
+ | `AppticsApi` | `startTrackApi(url, method?)` → id, `endTrackApi(id, responseCode, responseMessage?)`, `configure(config)`, `setApiTracking(enabled?)`, `ApiTrackingBuilder` | main |
89
+ | `AppticsHeatmap` | `setHeatmapTracking(enabled?)` | main |
90
90
  | `AppticsLogger` | `verbose(message, properties?)`, `debug(message, properties?)`, `info(message, properties?)`, `warn(message, properties?)`, `error(message, properties?)` | `/remote-logger` |
91
91
  | `AppticsFeedback` | `feedbackFormOpen(options?)`, `feedbackFormClose()`, `sendFeedback(options?)`, `addFeedbackLog(message)`, `addDiagnosticsInfo(heading, key, value)`, `setFeedbackTheme(theme)`, the `AP_FEEDBACK_TYPE` constants | `/feedback` |
92
- | `AppticsRemoteConfig` | `fetchValue(name, callback?)`, `fetchValues(names?, callback?)`, `setCustomConditionValue(conditionname, value)` | `/remote-config` |
92
+ | `AppticsRemoteConfig` | `fetchValue(name, callback?, coldFetch?)`, `fetchValues(names?, callback?, coldFetch?)`, `setCustomConditionValue(conditionname, value)` | `/remote-config` |
93
93
 
94
- The package exports only these objects: `DefinedEvents` is `AppticsEvent.DefinedEvents`, and the builders are `AppticsApi.ApiTrackingBuilder` and `AppticsUser.UserBuilder`. Android's `AppticsScreenTracker` and `AppticsApiTracker` are `AppticsScreen` and `AppticsApi` here.
94
+ The `set…Tracking(enabled?)` calls switch each automatic tracker on or off while the page runs
95
+ (see [Turning automatic tracking on and off](#turning-automatic-tracking-on-and-off)).
95
96
 
96
97
  ### Frameworks
97
98
 
98
- React, Vue, Angular, Svelte, Ember, Solid, jQuery and hand-written JS all start the same way, and every one of them needs only that: the SDK follows the route itself ([automatic screen tracking](#automatic-screen-tracking)). To name screens from your router instead, call `AppticsScreen.inScreen()` from the hook in the last column: a call made as the route changes replaces the automatic view, and `track_screen: false` turns the automatic one off altogether, which is what the recipes in `examples/frameworks` do.
99
+ React, Vue, Angular, Svelte, Ember, Solid, jQuery and hand-written JS all start the same way, and every one of them needs only that: the SDK follows the route itself ([automatic screen tracking](#automatic-screen-tracking)). To name screens from your router instead, call `AppticsScreen.inScreen()` from the hook in the last column: a call made as the route changes replaces the automatic view, and `track_screen: false` turns the automatic one off altogether.
99
100
 
100
101
  | Framework | Start | Screen on navigation, with `track_screen: false` |
101
102
  |---|---|---|
@@ -108,8 +109,6 @@ React, Vue, Angular, Svelte, Ember, Solid, jQuery and hand-written JS all start
108
109
  | Nuxt 3 | `plugins/apptics.client.ts` | `useRouter().afterEach(…)` |
109
110
  | Plain JS, jQuery | the `<script>` tag itself | `AppticsScreen.inScreen()` where you change view |
110
111
 
111
- **Server-side rendering** (Next, Nuxt, SvelteKit, Remix, Angular Universal): importing the SDK on the server is safe (`Apptics.init()` returns `false` instead of throwing), but it tracks nothing there. Start it from a browser-only hook, as the recipes do. There is no Node/server-side tracking: `engines.node` in `package.json` is the floor for building the package and running its CLI.
112
-
113
112
  ## Error Tracking
114
113
 
115
114
  Uncaught errors and unhandled promise rejections are tracked automatically, as JS errors in the console.
@@ -126,7 +125,15 @@ try {
126
125
  }
127
126
  ```
128
127
 
129
- `AppticsError.trackError` also accepts `error` and `unhandledrejection` events as they are, and properties as a second argument. Turn the automatic tracking off with `AppticsError.trackGlobalErrorHandler(false)`.
128
+ `AppticsError.trackError` also accepts `error` and `unhandledrejection` events as they are, and properties as a second argument.
129
+
130
+ To record only the errors you report yourself, turn the automatic tracking off, at start-up or
131
+ later. `AppticsError.trackError()` records either way:
132
+
133
+ ```ts
134
+ Apptics.init({ ...config, track_error: false }); // from the start
135
+ AppticsError.setErrorTracking(false); // or while the page runs; true turns it back on
136
+ ```
130
137
 
131
138
  React, Vue, Angular, SvelteKit and Ember catch render errors themselves, so those never reach `window.onerror`. Report them from the framework's own error hook:
132
139
 
@@ -140,22 +147,37 @@ React, Vue, Angular, SvelteKit and Ember catch render errors themselves, so thos
140
147
 
141
148
  ## Event Tracking
142
149
 
143
- Track an event, with an optional group and properties:
150
+ Track an event in a group, with optional properties:
144
151
 
145
152
  ```ts
146
153
  import { AppticsEvent } from '@zoho_apptics/apptics-js-sdk';
147
154
 
155
+ AppticsEvent.addEvent('eventName', 'eventGroupName');
148
156
  AppticsEvent.addEvent('eventName', 'eventGroupName', { propKey: 'propValue' });
149
157
  ```
150
158
 
159
+ The group is required. An event without one (left out, `''`, or properties in its place, as in
160
+ `addEvent('eventName', { propKey: 'propValue' })`) is not logged, and the console says so, debug
161
+ or not:
162
+
163
+ ```
164
+ AppticsEvent.addEvent: groupName is required for "eventName": addEvent(eventName, groupName, properties?)
165
+ ```
166
+
151
167
  Event and group names start with a letter, followed by letters, digits or `_`, at most 100
152
- characters, and may not start with `ap_` or `AP_`, which is reserved for defined events. As on
153
- Android, an event with an invalid name or group is not logged, and the console says why. A group
154
- left out is `default`.
168
+ characters, and may not start with `ap_` or `AP_`, which is reserved for defined events. An event
169
+ with an invalid name or group is not logged, and the console says why.
170
+
171
+ Properties: keys start with a letter, followed by up to 49 letters, digits or `_`, and may not
172
+ start with `ap_`. Values are numbers, booleans or strings of up to 250 characters; anything else
173
+ (an object, an array) is sent as its JSON text. A property that breaks these rules
174
+ is dropped and the event is still logged with the rest. At most 24 properties and 7,666
175
+ characters in all; past that the later ones are dropped. The same rules apply to screen and error
176
+ properties.
155
177
 
156
178
  ### Defined events
157
179
 
158
- Apptics' ready-made events, as Android's `DefinedEvents`, each with its own `AP_` group. They are
180
+ Apptics' ready-made events, each with its own `AP_` group. They are
159
181
  not tracked automatically; log the ones that apply:
160
182
 
161
183
  ```ts
@@ -177,7 +199,9 @@ AppticsEvent.addEvent(DefinedEvents.AP_SEARCH, { results: 12 });
177
199
 
178
200
  With a `<script>` tag it is `AppticsEvent.DefinedEvents` too.
179
201
 
180
- Clicks can also be tracked from markup, without code:
202
+ ### Click tracking
203
+
204
+ Clicks can be tracked from attributes in your markup, with no code:
181
205
 
182
206
  ```html
183
207
  <section apgroupaction="checkout">
@@ -185,21 +209,27 @@ Clicks can also be tracked from markup, without code:
185
209
  </section>
186
210
  ```
187
211
 
188
- Clicking the button, or anything inside it, tracks `buy_clicked` in group `checkout`. The
189
- `data-` spellings work too (`data-apeventaction`, `data-apgroupaction`, `data-apeventprops`), which
190
- React and TypeScript accept as they are.
212
+ Clicking the button, or anything inside it, tracks `buy_clicked` in group `checkout`, the nearest
213
+ `apgroupaction` around it, with the properties in `apeventprops` (JSON). An element with no
214
+ `apgroupaction` around it is not tracked, and the console says the group is missing. The `data-`
215
+ spellings work too (`data-apeventaction`, `data-apgroupaction`, `data-apeventprops`), which React
216
+ and TypeScript accept as they are.
217
+
218
+ #### Turning click tracking off
219
+
220
+ `track_click: false` in `Apptics.init()`, or `AppticsEvent.setClickTracking(false)` while the page
221
+ runs, stops click tracking from markup. `AppticsEvent.addEvent()` records either way.
222
+
223
+ ```ts
224
+ Apptics.init({ ...config, track_click: false }); // from the start
225
+ AppticsEvent.setClickTracking(true); // or switch it later
226
+ ```
191
227
 
192
- Properties: keys start with a letter, followed by up to 49 letters, digits or `_`, and may not
193
- start with `ap_`. Values are numbers, booleans or strings of up to 250 characters; anything else
194
- (an object, an array) is sent as its JSON text. As on Android, a property that breaks these rules
195
- is dropped and the event is still logged with the rest. At most 24 properties and 7,666
196
- characters in all; past that the later ones are dropped. The same rules apply to screen and error
197
- properties.
198
228
 
199
229
  ## Screen Tracking
200
230
 
201
231
  Screens are tracked automatically, from the URL (see [below](#automatic-screen-tracking)). To
202
- record one yourself, with your own name or with properties, call `AppticsScreen.inScreen`, as on Android:
232
+ record one yourself, with your own name or with properties, call `AppticsScreen.inScreen`:
203
233
 
204
234
  ```ts
205
235
  import { AppticsScreen } from '@zoho_apptics/apptics-js-sdk';
@@ -210,7 +240,7 @@ AppticsScreen.inScreen('checkout');
210
240
  Each screen view records how long it lasted. It ends when the next screen starts, when the page
211
241
  is hidden (coming back starts a new view of the same screen), or when its session ends.
212
242
  `AppticsScreen.inScreen` returns the view's id; hand it to `AppticsScreen.outScreen` to end the view yourself (a dialog
213
- that closes without the page changing, say), as Android's `AppticsScreenTracker.outScreen` does:
243
+ that closes without the page changing, say):
214
244
 
215
245
  ```ts
216
246
  import { AppticsScreen } from '@zoho_apptics/apptics-js-sdk';
@@ -283,6 +313,13 @@ aren't routes, or hooks that run later than that), turn automatic tracking off:
283
313
  Apptics.init({ ...config, track_screen: false });
284
314
  ```
285
315
 
316
+ or switch it while the page runs, for a part of the app that names its screens itself:
317
+
318
+ ```ts
319
+ AppticsScreen.setScreenTracking(false); // only inScreen() calls are recorded
320
+ AppticsScreen.setScreenTracking(true); // back on: the page as it is now is recorded
321
+ ```
322
+
286
323
  `Apptics.reset()` takes the history wrappers off; the `Apptics.init()` it runs puts them back.
287
324
 
288
325
  ## Track User
@@ -348,10 +385,10 @@ Record the API calls your app makes, for the console's API page. Either let the
348
385
  Apptics.init({ ...config, track_api: true }); // record every fetch and XHR call
349
386
  ```
350
387
 
351
- `AppticsApi.enableApiTracking(enabled)` switches it later. Which hosts and endpoints are recorded is set with
388
+ `AppticsApi.setApiTracking(enabled)` switches it later. Which hosts and endpoints are recorded is set with
352
389
  [`AppticsApi.configure`](#configuring-api-tracking).
353
390
 
354
- or record calls yourself with `AppticsApi.startTrackApi` / `endTrackApi`, as on Android. The
391
+ or record calls yourself with `AppticsApi.startTrackApi` / `endTrackApi`. The
355
392
  SDK times the call between the two:
356
393
 
357
394
  ```ts
@@ -414,7 +451,7 @@ The rules apply to every call, the ones `track_api` catches and the ones you rep
414
451
 
415
452
  The SDK's own requests are never recorded, and neither are calls to `localhost` or a bare IP
416
453
  address: the server only accepts hostnames with a dot and a letters-only suffix, so the SDK drops
417
- those calls and says so in the console. `AppticsApi.enableApiTracking(false)` removes the wrappers again.
454
+ those calls and says so in the console. `AppticsApi.setApiTracking(false)` removes the wrappers again.
418
455
  With a `<script>` tag, `AppticsApi` is a global as it is here, `AppticsApi.ApiTrackingBuilder`
419
456
  included.
420
457
 
@@ -429,6 +466,7 @@ const banner = await AppticsRemoteConfig.fetchValue('bannerText'); // nu
429
466
  const some = await AppticsRemoteConfig.fetchValues(['primaryColor', 'maxItems']);
430
467
  // → { primaryColor: '#0b6e4f', maxItems: '10' }
431
468
  const all = await AppticsRemoteConfig.fetchValues(); // every parameter
469
+ const fresh = await AppticsRemoteConfig.fetchValue('bannerText', true); // coldFetch: asks the server now
432
470
 
433
471
  // for a custom condition: its name, then this device's values, comma separated
434
472
  AppticsRemoteConfig.setCustomConditionValue('is_custom', 'custom_color');
@@ -447,10 +485,13 @@ Values are text, as the console stores them: `Number(values.maxItems)`,
447
485
  The SDK fetches once on its own when it starts (or when this module is imported after it has),
448
486
  so values are this session's without a call of yours.
449
487
 
450
- **Fetching.** `fetchValue` and `fetchValues` reuse a fetch from the last five minutes
451
- rather than asking the server again, so reading a value on every render costs no requests; once
452
- that fetch is older, the next call asks the server. Each also takes a callback, as on Android,
453
- and returns a Promise either way.
488
+ **Fetching.** The first fetch of each page load asks for the whole rule set, and its answer
489
+ replaces what was stored. After that the SDK keeps the values up to date by itself: every 3
490
+ minutes, and when the tab comes back after 15 seconds or more away, it asks only for what changed
491
+ since its last fetch and merges that into the stored set. `fetchValue` and `fetchValues` answer
492
+ from those values, so reading a value on every render costs no requests. Each also takes a
493
+ callback, and returns a Promise either way. To ask the server now instead, see
494
+ [Cold fetch](#cold-fetch).
454
495
 
455
496
  **When a fetch fails** (offline, or a server error), they answer with the values fetched before;
456
497
  with none fetched yet, `null` (and `fetchValues()` answers with no parameters).
@@ -467,18 +508,44 @@ Conditions on the user, such as the customer group, are re-applied on their own
467
508
 
468
509
  | Call | Notes |
469
510
  |---|---|
470
- | `fetchValue(name, callback?)` | One parameter for this session; `null` when the console has none. |
471
- | `fetchValues(names?, callback?)` | The parameters named in the list, `null` for a missing one; with no names, every parameter. `fetchValues(callback)` works too. |
511
+ | `fetchValue(name, callback?, coldFetch?)` | One parameter for this session; `null` when the console has none. `fetchValue(name, coldFetch)` works too. `coldFetch: true` asks the server now (see [Cold fetch](#cold-fetch)). |
512
+ | `fetchValues(names?, callback?, coldFetch?)` | The parameters named in the list, `null` for a missing one; with no names, every parameter. `fetchValues(callback)`, `fetchValues(names, coldFetch)` and `fetchValues(coldFetch)` work too. |
472
513
  | `setCustomConditionValue(conditionname, value)` | This device's values for a custom condition, comma separated (`'gold,platinum'`); an empty value removes them. |
473
514
 
474
515
  With a `<script>` tag, `AppticsRemoteConfig` is a global as it is here.
475
516
 
517
+ ### Cold fetch
518
+
519
+ By default `fetchValue` and `fetchValues` answer from the values the page already has, which the
520
+ SDK keeps up to date every 3 minutes. For a value that must be current now, say right after it was
521
+ changed in the console, or before a step that depends on it, pass `true` as the last argument:
522
+ `fetchValue('bannerText', true)`, `fetchValues(['primaryColor', 'maxItems'], true)`,
523
+ `fetchValues(true)` for every parameter, or after a callback, as in
524
+ `fetchValue('bannerText', render, true)`.
525
+
526
+ What a cold fetch does:
527
+
528
+ - It asks the server for the whole rule set now (`getupdates` with `flagtime` 0), whatever the page
529
+ has already fetched, and the answer **replaces** the stored set, as the first fetch of a page
530
+ load does. The value is then chosen from it as usual, and the SDK's 3-minute updates go on from
531
+ there.
532
+ - It waits for start-up, and on a first visit for the device to be registered, before asking:
533
+ calling it straight after `Apptics.init()` is fine.
534
+ - **At most three cold fetches in any minute**, per page. One past that makes no request and
535
+ answers from the values the page already has, as `coldFetch: false` would; with
536
+ `console_log: true`, the console says so.
537
+ - Cold fetches made at the same time share one request.
538
+ - If it fails (offline, or a server error), it answers from the values fetched before, or `null`
539
+ with none fetched yet, as any fetch does.
540
+
541
+ `coldFetch` is `false` by default. Use it for the moments that need it, not on every read: each
542
+ one is a request for the whole rule set.
543
+
476
544
  ## Remote Logger
477
545
 
478
546
  Send your app's log lines to the console's Remote Logger page with `AppticsLogger`, from its own
479
547
  entry point (`@zoho_apptics/apptics-js-sdk/remote-logger`) so apps that don't log don't ship it.
480
- Nothing is logged on its own: only the lines your app writes, at five levels, as Android's
481
- `v` / `d` / `i` / `w` / `e` with their names in full. A line is recorded as it is written, with no
548
+ Nothing is logged on its own: only the lines your app writes, at five levels. A line is recorded as it is written, with no
482
549
  switch to turn on first:
483
550
 
484
551
  ```ts
@@ -503,12 +570,11 @@ AppticsLogger.error('Payment failed', err); // an Error as properties:
503
570
  an `Error` as its stack. Each line records the time it was logged and the function, file and line
504
571
  that logged it, even when logged before start-up finishes. Lines are stored before they are sent
505
572
  and go out in batches of up to 50: a line survives a failed send and a reload, and is removed once
506
- the server accepts it. At most 1 MB of lines waits at once, oldest dropped first, as on Android,
573
+ the server accepts it. At most 1 MB of lines waits at once, oldest dropped first,
507
574
  and a line is trimmed to 10,000 characters. Nothing is recorded while the server has the remote
508
575
  logger switched off for the app, or while tracking is off.
509
576
 
510
- Unlike Android, which uploads at the next cold start or on a schedule, lines go out about a
511
- second after they're logged: a browser tab can close at any moment, and waiting would lose them.
577
+ Lines go out about a second after they're logged: a browser tab can close at any moment, and waiting would lose them.
512
578
 
513
579
  ## In-App Feedback
514
580
 
@@ -640,15 +706,15 @@ main entry point and off until you turn it on.
640
706
  import { Apptics, AppticsHeatmap } from '@zoho_apptics/apptics-js-sdk';
641
707
 
642
708
  Apptics.init({ ...config, track_heatmap: true });
643
- // or turn it on later: AppticsHeatmap.trackHeatmap(true)
709
+ // or turn it on later: AppticsHeatmap.setHeatmapTracking(true)
644
710
  ```
645
711
 
646
712
  `track_heatmap: true` in `Apptics.init()` starts capture with the SDK. With a `<script>` tag it's
647
- `AppticsHeatmap.trackHeatmap()` on the `AppticsHeatmap` global.
713
+ `AppticsHeatmap.setHeatmapTracking()` on the `AppticsHeatmap` global.
648
714
 
649
715
  | Call | Notes |
650
716
  |---|---|
651
- | `AppticsHeatmap.trackHeatmap(on?)` | Starts or stops capture; `on` defaults to `true`. |
717
+ | `AppticsHeatmap.setHeatmapTracking(enabled?)` | Starts or stops capture; `enabled` defaults to `true`. |
652
718
 
653
719
  Heatmap records go out with the rest of the stored data: on the flush timer, or when you call
654
720
  `Apptics.flush()`.
@@ -709,6 +775,8 @@ Everything `Apptics.init(config)` accepts.
709
775
  | `track_heatmap` | | Record clicks and scrolls (see [Heatmaps](#heatmaps)). Off by default |
710
776
  | `heatmap_max_per_session` | | Most heatmap records one visit may produce: 500 by default, 0 to 10000. Capture pauses past it |
711
777
  | `track_screen` | | Record a screen view for every navigation, named by its path. On by default; `false` turns it off (see [Automatic screen tracking](#automatic-screen-tracking)) |
778
+ | `track_error` | | Record uncaught errors and unhandled promise rejections. On by default; `false` turns it off (see [Error Tracking](#error-tracking)) |
779
+ | `track_click` | | Record clicks on elements tagged `apeventaction`. On by default; `false` turns it off (see [Click tracking](#click-tracking)) |
712
780
  | `screen_routes` | | How automatic screen tracking names a path: route patterns (`'/users/{id}/orders'`), `{ equals, name }` and `{ regex, name }` rules, tried in order (see [Automatic screen tracking](#automatic-screen-tracking)) |
713
781
  | `feedback_theme` | | The feedback form's theme: `'light'`, `'dark'` or `'auto'` (the default, which follows the visitor's system setting). See [Show feedback screen](#show-feedback-screen) |
714
782
  | `device_name` | | Names this device in debug mode (see [Debugging](#debugging)) |
@@ -717,45 +785,55 @@ The earlier names still work, with a console warning naming the key to use: `ser
717
785
  `base_domain` for `base_url`, `zak` and `token` for `auth_key`, and `identifier` for `app_domain`.
718
786
  `aaid`, `zsoid` and `projectID` are no longer needed, and are ignored if passed.
719
787
 
720
- ### Timing
788
+ **Changing `base_url`, `app_domain` or `auth_key`.** What the SDK stores in a browser belongs to
789
+ the app it was registered with. When a page starts with a different `base_url`, `app_domain` or
790
+ `auth_key` from the stored data's, the SDK clears all of it, unsent data included, and starts as on
791
+ a first visit: the app version and the device are registered again. Only a short fingerprint of
792
+ `auth_key` is stored, not the key itself.
721
793
 
722
- Data is stored first and sent on a timer, so these control how often the SDK talks to the server. All are optional; a value outside its range is ignored with a warning and the default is used.
794
+ `Apptics.flush()` sends at most once every 15 seconds, however often it is called: a call sooner
795
+ than that sends nothing, and what is stored goes with the next send.
723
796
 
724
- | Key | Default | Range | Description |
725
- |---|---|---|---|
726
- | `batch_flush_interval` | `30000` | 1000 to 3600000 | How often stored data is sent, in milliseconds |
727
- | `getupdates_interval` | `120000` | 10000 to 86400000 | How often the server's tracking settings are checked, in milliseconds; the server can ask for a longer wait |
728
- | `batch_size` | `50` | 1 to 500 | Most items in one request (also capped at 1 MB) |
729
- | `batch_request_timeout` | `7` | 1 to 30 | Days an unsent item is kept before it is dropped |
730
- | `inactiveduration` | `30` | 1 to 1440 | Idle minutes that end a session |
731
- | `min_session_duration` | `5000` | 0 to 60000 | Milliseconds a visit must last before its session is recorded; anything tracked sooner records it at once. `0` turns the wait off |
797
+ ### Turning automatic tracking on and off
732
798
 
733
- Data is also sent when you call `Apptics.flush()`, when the page is hidden, when the tab closes, and when the browser comes back online. The interval is the floor, not the only trigger.
799
+ Each tracker the SDK runs on its own has a config key, read when `Apptics.init()` runs, and a call
800
+ to switch it while the page runs. The call takes `true` or `false`; with no argument it means
801
+ `true`.
734
802
 
735
- ## API reference
736
-
737
- | Call | Notes |
738
- |---|---|
739
- | `Apptics.init(config)` | Starts the SDK. Returns `true` when start-up has begun. |
740
- | `Apptics.ready()` | Promise that resolves `true` once the SDK is running (`false` if it can't start). |
741
- | `AppticsEvent.addEvent(eventName, groupName?, properties?)` / `AppticsEvent.addEvent(AppticsEvent.DefinedEvents.X, properties?)` | See [Event Tracking](#event-tracking). |
742
- | `AppticsScreen.inScreen(screenName, properties?)` → id / `AppticsScreen.outScreen(id)` | See [Screen Tracking](#screen-tracking). |
743
- | `AppticsError.trackError(error, properties?)` / `AppticsError.trackGlobalErrorHandler(enabled?)` | See [Error Tracking](#error-tracking). |
744
- | `AppticsUser.setUser(userid, groupid?, properties?)` / `AppticsUser.getUser()` / `AppticsUser.UserBuilder` | See [Track User](#track-user). |
745
- | `AppticsSettings.setTrackingStatus(status)` / `AppticsSettings.getTrackingStatus()` / `AppticsSettings.AP_TRACKING_STATUS` | See [Tracking settings](#tracking-settings). |
746
- | `AppticsApi.startTrackApi(url, method?)` / `endTrackApi(id, responseCode, responseMessage?)` / `configure(config)` / `enableApiTracking(enabled?)` / `AppticsApi.ApiTrackingBuilder` | See [API Tracking](#api-tracking). |
747
- | `AppticsLogger.verbose / debug / info / warn / error(message, properties?)` | From `/remote-logger`; see [Remote Logger](#remote-logger). |
748
- | `AppticsRemoteConfig.fetchValue(name, callback?)` / `fetchValues(names?, callback?)` / `setCustomConditionValue(conditionname, value)` | From `/remote-config`; see [Remote Config](#remote-config). |
749
- | `AppticsFeedback.addFeedbackLog(message)` / `AppticsFeedback.addDiagnosticsInfo(heading, key, value)` | From `/feedback`; see [Attach logs and diagnostics](#attach-logs-and-diagnostics-with-feedback). |
750
- | `AppticsFeedback.feedbackFormOpen(options?)` / `feedbackFormClose()` / `sendFeedback(options?)` / `setFeedbackTheme(theme)` / `AppticsFeedback.AP_FEEDBACK_TYPE` | From `/feedback`; see [In-App Feedback](#in-app-feedback). |
751
- | `AppticsHeatmap.trackHeatmap(on?)` | See [Heatmaps](#heatmaps). |
752
- | `Apptics.flush()` | Send stored data now (engagement, errors and heatmap records); it's otherwise sent every 30 s (see [Timing](#timing)). |
753
- | `Apptics.enableDebug()` / `Apptics.disableDebug()` | See [Debugging](#debugging). |
754
- | `Apptics.reset()` | Clear stored identity, queued data and remote config values, then start again. |
755
-
756
- Entry points: `@zoho_apptics/apptics-js-sdk` (everything above except what follows), `/feedback`, `/remote-config`
757
- (see [Remote Config](#remote-config)), `/remote-logger` (see [Remote Logger](#remote-logger)). Types ship with the package:
758
- `import type { AppticsConfig, TrackingStatus } from '@zoho_apptics/apptics-js-sdk'`.
803
+ | Tracker | Default | Config key | Call |
804
+ |---|---|---|---|
805
+ | Screen views from the URL | on | `track_screen` | `AppticsScreen.setScreenTracking(enabled)` |
806
+ | Uncaught errors and unhandled rejections | on | `track_error` | `AppticsError.setErrorTracking(enabled)` |
807
+ | Clicks on tagged elements | on | `track_click` | `AppticsEvent.setClickTracking(enabled)` |
808
+ | The app's fetch and XHR calls | off | `track_api` | `AppticsApi.setApiTracking(enabled)` |
809
+ | Clicks and scrolls for heatmaps | off | `track_heatmap` | `AppticsHeatmap.setHeatmapTracking(enabled)` |
810
+
811
+ - The config key decides at start-up. A call made before `Apptics.init()` is replaced by it, and
812
+ `Apptics.reset()` goes back to the config too.
813
+ - The calls you make yourself (`addEvent`, `inScreen`, `trackError`, `startTrackApi`) record
814
+ whichever way a switch is set.
815
+ - To stop all tracking for a visitor, use
816
+ `AppticsSettings.setTrackingStatus(AppticsSettings.AP_TRACKING_STATUS.NO_TRACKING)` instead (see
817
+ [Tracking settings](#tracking-settings)).
818
+
819
+ The 2.0.0-beta.1 names of three of these calls still work, with a console warning naming the one to
820
+ use: `AppticsApi.enableApiTracking`, `AppticsError.trackGlobalErrorHandler` and
821
+ `AppticsHeatmap.trackHeatmap`.
822
+
823
+ ### Sessions
824
+
825
+ A session starts with the visit and goes on while the user comes back to the tab within
826
+ `inactiveduration` minutes (30 by default).
827
+
828
+ - When the tab goes inactive (hidden, minimised, or its window loses focus to another one), that
829
+ moment is the session's last active time. Moving focus into an iframe on the page does not count.
830
+ - Back within `inactiveduration`, the same session goes on.
831
+ - Not back by then, the session ends at its last active time and is sent, so the time away is not
832
+ counted. Coming back later starts a new session.
833
+ - A tab closed while inactive ends its session at its last active time too, not when it closed; a
834
+ tab closed while in use ends it then.
835
+ - While another tab of the site is still on the session, a tab that goes inactive or closes only
836
+ leaves it: the last one ends it.
759
837
 
760
838
  ## Loading from a CDN
761
839
 
@@ -763,9 +841,12 @@ For `<script type="module">`, load the minified ESM build (a few requests instea
763
841
 
764
842
  ```html
765
843
  <script type="module">
766
- import { Apptics, AppticsEvent } from 'https://cdn.jsdelivr.net/npm/@zoho_apptics/apptics-js-sdk@2.0.0-beta.1/dist/apptics.esm.min.js';
767
- // The feedback form is a separate file, so pages without it don't download it
768
- import { AppticsFeedback } from 'https://cdn.jsdelivr.net/npm/@zoho_apptics/apptics-js-sdk@2.0.0-beta.1/dist/feedback.esm.min.js';
844
+ import { Apptics, AppticsEvent } from 'https://static.zohocdn.com/apptics-js-sdk/2.0.0-beta.2/apptics.esm.min.js';
845
+ // Feedback, remote config and the remote logger are files of their own, so a page downloads
846
+ // only the ones it imports
847
+ import { AppticsFeedback } from 'https://static.zohocdn.com/apptics-js-sdk/2.0.0-beta.2/feedback.esm.min.js';
848
+ import { AppticsRemoteConfig } from 'https://static.zohocdn.com/apptics-js-sdk/2.0.0-beta.2/remoteconfig.esm.min.js';
849
+ import { AppticsLogger } from 'https://static.zohocdn.com/apptics-js-sdk/2.0.0-beta.2/remotelogger.esm.min.js';
769
850
 
770
851
  Apptics.init({
771
852
  base_url: 'YOUR_BASE_URL',
@@ -780,16 +861,18 @@ For `<script type="module">`, load the minified ESM build (a few requests instea
780
861
 
781
862
  | File | For | Size (gzipped) |
782
863
  |---|---|---|
783
- | `dist/apptics.min.js` | `<script>` pages; sets `window.apptics`, includes every module | ~53 kB |
784
- | `dist/apptics.esm.min.js` | `<script type="module">`; analytics only (with the `dist/chunks/` files it imports) | ~30 kB |
785
- | `dist/feedback.esm.min.js` | the feedback form, for module pages | ~17 kB more |
864
+ | `apptics.min.js` | `<script>` pages; sets `window.apptics`, includes every module | ~53 kB |
865
+ | `apptics.esm.min.js` | `<script type="module">`; the main entry (with the `chunks/` files it imports) | ~32 kB |
866
+ | `feedback.esm.min.js` | `AppticsFeedback`, the feedback form, for module pages | ~17 kB more |
867
+ | `remoteconfig.esm.min.js` | `AppticsRemoteConfig`, for module pages | ~7 kB more |
868
+ | `remotelogger.esm.min.js` | `AppticsLogger`, for module pages | ~1 kB more |
786
869
 
787
- The module files share one copy of the SDK through `dist/chunks/`, so load them all from the same version and path.
870
+ The module files share one copy of the SDK through the `chunks/` folder beside them, so load them all from the same version's folder.
788
871
 
789
- unpkg works the same way: `https://unpkg.com/@zoho_apptics/apptics-js-sdk@2.0.0-beta.1/dist/apptics.min.js`. Add `defer` if you don't need the SDK before the page renders. For a subresource-integrity hash:
872
+ Every release is in a folder of its own, `https://static.zohocdn.com/apptics-js-sdk/{version}/`, holding `apptics.min.js`, `apptics.esm.min.js`, `feedback.esm.min.js`, `remoteconfig.esm.min.js`, `remotelogger.esm.min.js`, `chunks/` and the source maps. Add `defer` if you don't need the SDK before the page renders. For a subresource-integrity hash:
790
873
 
791
874
  ```bash
792
- curl -s https://cdn.jsdelivr.net/npm/@zoho_apptics/apptics-js-sdk@2.0.0-beta.1/dist/apptics.min.js \
875
+ curl -s https://static.zohocdn.com/apptics-js-sdk/2.0.0-beta.2/apptics.min.js \
793
876
  | openssl dgst -sha384 -binary | openssl base64 -A
794
877
  ```
795
878
 
@@ -797,20 +880,20 @@ curl -s https://cdn.jsdelivr.net/npm/@zoho_apptics/apptics-js-sdk@2.0.0-beta.1/d
797
880
  <script src="…/apptics.min.js" integrity="sha384-…" crossorigin="anonymous"></script>
798
881
  ```
799
882
 
800
- ## Migrating from 1.0.2 to 2.0.0-beta.1
883
+ ## Migrating from 1.0.2 to 2.0.0-beta.2
801
884
 
802
885
  ### What you need to change
803
886
 
804
887
  - **Every call is on the object of its feature.** Rename them everywhere, router hooks included: a
805
888
  call to an old name left in place throws.
806
889
 
807
- | 1.0.2 | 2.0.0-beta.1 |
890
+ | 1.0.2 | 2.0.0-beta.2 |
808
891
  |---|---|
809
892
  | `apptics.init(config)` | `Apptics.init(config)` |
810
893
  | `apptics.trackEvent(name, group, props)` | `AppticsEvent.addEvent(eventName, groupName, properties)` |
811
894
  | `apptics.trackScreen(name, props)` | `AppticsScreen.inScreen(screenName, properties)`, which also returns the view's id for `AppticsScreen.outScreen(id)` |
812
895
  | `apptics.trackError(event, props)` | `AppticsError.trackError(error, properties)` |
813
- | `apptics.enableGlobalErrorHandler(on)` | `AppticsError.trackGlobalErrorHandler(enabled)` |
896
+ | `apptics.enableGlobalErrorHandler(on)` | `AppticsError.setErrorTracking(enabled)`, or `track_error` in `Apptics.init()` |
814
897
  | `apptics.setUser(userid, groupid, props)` | `AppticsUser.setUser(userid, groupid, properties)` |
815
898
  | `apptics.getUser()`, `new users.UserBuilder()` | `AppticsUser.getUser()`, `new AppticsUser.UserBuilder()` |
816
899
  | `apptics.setTrackingStatus(s)`, `getTrackingStatus()` | `AppticsSettings.setTrackingStatus(status)`, `AppticsSettings.getTrackingStatus()` |
@@ -823,6 +906,10 @@ curl -s https://cdn.jsdelivr.net/npm/@zoho_apptics/apptics-js-sdk@2.0.0-beta.1/d
823
906
  required (1.0.2's `base_domain` and `token` still work, with a warning). The SDK gets `aaid` and the portal and project ids from the server itself, so
824
907
  `aaid`/`aaID`, `zsoid` and `projectID` are no longer needed and are ignored if passed. Without a
825
908
  required key, `Apptics.init()` logs which one is missing and returns `false`.
909
+ - **Every event needs a group.** 1.0.2 filed an event with no group under `default`; now it is
910
+ not logged, and the console says the group is missing. Pass one to every
911
+ `AppticsEvent.addEvent(eventName, groupName, properties?)`, and put an `apgroupaction` around
912
+ every element tracked with `apeventaction`. Defined events bring their own.
826
913
  - **`appversion` is required.** 1.0.2 quietly defaulted it to `1.0`, which attributed every session,
827
914
  error and crash to a version that was never shipped. Pass your real build version.
828
915
  - **npm users can import the SDK.** 1.0.2 exported nothing, so it only worked alongside the console
@@ -841,11 +928,11 @@ curl -s https://cdn.jsdelivr.net/npm/@zoho_apptics/apptics-js-sdk@2.0.0-beta.1/d
841
928
  ### Behaviour you may notice
842
929
 
843
930
  - **`debug: true` now turns on debug mode** (requests followed in the Apptics web console). In 1.0.2 it logged to the browser console.
844
- - When the Apptics server tells the SDK to stop tracking an app version, it stops; 1.0.2 ignored that signal.
931
+ - When the Apptics server tells the SDK to stop tracking an app version, it stops; 1.0.2 ignored that signal. Events, screens, sessions, API calls and errors each follow their own switch in the Apptics console, so turning one off leaves the others on.
845
932
  - `ignore_do_not_track: true` now ignores the browser's Do Not Track setting; in 1.0.2 it disabled tracking. Do Not Track is decided on every visit and never stored.
846
933
  - `mute()` and `unmute()` are gone. To stop tracking, use `AppticsSettings.setTrackingStatus(AppticsSettings.AP_TRACKING_STATUS.NO_TRACKING)`; unlike `mute()`, it is stored across visits. Feedback is still sent with tracking off.
847
934
  - **Screens are tracked automatically**, from the URL, including single-page route changes. An `AppticsScreen.inScreen()` called from your router replaces the automatic view of that navigation, so nothing is counted twice; `track_screen: false` turns automatic tracking off, and `screen_routes` names paths. Each screen view now records how long it lasted.
848
- - **Events and properties follow the Android rules**: an event with an invalid group is not logged (a missing group is still `default`), names and keys may not start with `ap_`, and a bad property is dropped on its own rather than taking the others with it. Booleans arrive as Boolean, and `1` / `0` as Number. An invalid name is said in the console.
935
+ - **Events and properties are checked**: an event with a missing or invalid group is not logged, names and keys may not start with `ap_`, and a bad property is dropped on its own rather than taking the others with it. Booleans arrive as Boolean, and `1` / `0` as Number. An invalid name is said in the console.
849
936
  - Calling `Apptics.init()` a second time is ignored; use `Apptics.reset()` to start over.
850
937
  - `Apptics.init()` still returns at once, but start-up finishes a few milliseconds later, once storage loads, so `window.appticsReady()` fires slightly later than in 1.0.2. Calls made in between are queued and replayed; `await Apptics.ready()` waits for it. A first visit with no network starts once the browser is back online.
851
938
  - `AppticsFeedback.sendFeedback()` returns a Promise. `includeLog` and `includeDiagnostics` are three-way: `true` always sends that file, `false` never does, and leaving it unset sends it when something is stored.
@@ -853,7 +940,7 @@ curl -s https://cdn.jsdelivr.net/npm/@zoho_apptics/apptics-js-sdk@2.0.0-beta.1/d
853
940
  - Clicks tracked with `apeventaction` (or `data-apeventaction`) no longer need jQuery.
854
941
  - Data moves from localStorage to IndexedDB on the first visit (device identity, consent, unsent events, feedback log entries), and the old keys are removed. Where IndexedDB is unavailable, the SDK keeps using localStorage.
855
942
  - Queued data is sent when the page is hidden or closed, using `pagehide` / `visibilitychange` instead of `beforeunload`.
856
- - New, and off until you use them: heatmaps (`AppticsHeatmap.trackHeatmap()`), remote config, API tracking and the remote logger (`AppticsLogger`). Remote config, once imported, fetches its values on start-up.
943
+ - New, and off until you use them: heatmaps (`AppticsHeatmap.setHeatmapTracking()`), remote config, API tracking and the remote logger (`AppticsLogger`). Remote config, once imported, fetches its values on start-up.
857
944
 
858
945
  ## License
859
946
 
@@ -1,3 +1,3 @@
1
- /*! @zoho_apptics/apptics-js-sdk v2.0.0-beta.1 | (c) Zoho Corporation Private Limited | see LICENSE */
2
- import{o as e,C as t,B as n,n as r,c as a,D as i,E as s,G as o,H as c,_ as u,d as l,j as p,e as d,I as f,J as g,K as m,A as h,L as _,M as w,N as A,b as v,O as b,P as k,Q as y,R as T,S as E,T as H,U as S,V as M,w as x,W as U,X as D,Y as L,Z as N,$ as O,x as P,a0 as Y,y as C,a1 as G,z as W,a2 as X,a3 as j,a4 as I,a5 as z,a6 as q,a7 as B,a8 as K,a9 as R,aa as J,ab as Q,ac as V,ad as Z,ae as $,af as F,ag as ee,ah as te}from"./chunks/lifecycle-VYr43KcB.min.js";var ne=!1,re=0,ae=[],ie=0,se=0,oe=0,ce=null,ue=null,le=new WeakMap,pe=0,de=0;function fe(){var e=o("heatmap_max_per_session");return("number"!=typeof e||e<=0)&&(e=c.heatmap_max_per_session),!(re>=e)||(re===e&&(re++,t.log("apptics.heatmap: reached "+e+" records for this session, pausing capture")),!1)}function ge(){var e=document.documentElement,t=document.body;return Math.max(e?e.scrollHeight:0,t?t.scrollHeight:0,e?e.clientHeight:0)}function me(e,t){if(!t||t<=0)return 0;var value=e/t;return value<0&&(value=0),value>1&&(value=1),Math.round(1e3*value)/1e3}function he(){return window.innerWidth||(document.documentElement?document.documentElement.clientWidth:0)||1}function _e(e){if(!e)return"";for(var t=["data-ap-label","apeventaction","data-apeventaction","aria-label","name","id","title"],n=0;n<t.length;n++){var value=e.getAttribute?e.getAttribute(t[n]):null;if(!a(value))return String(value).slice(0,80)}var r=e.tagName?e.tagName.toLowerCase():"element";if(m()!==h.USAGE_TRACKING_WITH_PII){var i=e.getAttribute?e.getAttribute("role"):null;return a(i)?r:r+"["+i+"]"}var s=(e.textContent||"").replace(/\s+/g," ").trim();return a(s)?r:s.slice(0,80)}function we(e){if(!e)return 0;for(var t="",n=e,r=0;n&&r<12;){var a=n.parentElement,i=0;if(a)for(var s=a.children,o=0;o<s.length;o++)if(s[o]===n){i=o;break}t="/"+(n.tagName||"?")+":"+i+t,n=a,r++}for(var c=2166136261,u=0;u<t.length;u++)c=16777619*(c^=t.charCodeAt(u))>>>0;return c}function Ae(e,t,n){return(ae=ae.filter(function(e){return n-e.at<=1e3})).push({at:n,x:e,y:t}),ae.filter(function(n){return Math.abs(n.x-e)<=30&&Math.abs(n.y-t)<=30}).length>=3}function ve(){return{id:g(),session_start_time:u._current_session.starttime||r(),triggered_time:r(),screen:String(f()).slice(0,500),url_path:String(window.location.pathname).slice(0,500),screen_width:window.screen?window.screen.width:0,screen_height:window.screen?window.screen.height:0,content_height:ge(),orientation:d(),network_status:p(),edge_type:u._device_info.connectionType||l(),scroll_offset_x:Math.round(window.scrollX||window.pageXOffset||0),scroll_offset_y:Math.round(window.scrollY||window.pageYOffset||0)}}function be(e){re++,_(),w(),A.add(e),t.dir(e)}function ke(e){if(n("heatmap")&&fe())try{var t=r(),o=e.target,c=function(e){for(var t=0;e&&t<10;){var n=e.tagName?e.tagName.toLowerCase():"",r=e.getAttribute?e.getAttribute("role"):null;if("a"===n||"button"===n||"input"===n||"select"===n||"textarea"===n||"summary"===n||"label"===n||"button"===r||"link"===r||"tab"===r||"menuitem"===r||e.hasAttribute&&e.hasAttribute("onclick"))return e;e=e.parentElement,t++}return null}(o),u=c||o,l=Math.round(e.clientX),p=Math.round(e.clientY),d=ge()||1,f=e.pointerType,g=Object.assign(ve(),{triggered_type:"default",gesture_type:"click",gesture_duration:0,input_type:a(f)?"mouse":String(f),element_label:_e(u),triggered_id:we(u),coordinate_x:l,coordinate_y:p,normalized_x:me(l,he()),normalized_y:me((window.scrollY||0)+p,d),velocity:0,is_clickable:c?1:0,is_rage_click:Ae(l,p,t)?1:0,is_dead_click:0});be(g),function(e){if(1===e.is_clickable||"function"!=typeof MutationObserver)return;var t=!1,url=window.location.href,n=new MutationObserver(function(){t=!0});try{n.observe(document.documentElement,{childList:!0,subtree:!0,attributes:!0})}catch(e){return}setTimeout(function(){n.disconnect(),t||window.location.href!==url||(e.is_dead_click=1,A.update(e))},1500)}(g)}catch(e){i(s.HEATMAP,"apptics.heatmap: click capture failed: "+String(e))}}function ye(e){if(n("heatmap")&&fe()){var t=function(e){var t=document;if(!e||1!==e.nodeType||e===t.documentElement||e===t.body)return null;var n=e;return n.clientHeight>=.5*(window.innerHeight||0)&&n.clientWidth>=.5*he()?n:void 0}(e?e.target:null);if(void 0!==t){if(null!==ce&&t!==ue&&(clearTimeout(ce),Te()),null===ce){ue=t;var a=function(e){return null===e?{x:pe,y:de}:le.get(e)||{x:0,y:0}}(t);ie=r(),se=a.x,oe=a.y}else clearTimeout(ce);ce=setTimeout(Te,150)}}}function Te(){ce=null;var e=ue;ue=null;try{var t=function(e){return null===e?{x:Math.round(window.scrollX||window.pageXOffset||0),y:Math.round(window.scrollY||window.pageYOffset||0)}:{x:Math.round(e.scrollLeft||0),y:Math.round(e.scrollTop||0)}}(e),n=t.x,a=t.y,o=n-se,c=a-oe;if(null===e?(pe=n,de=a):le.set(e,t),0===o&&0===c)return;var u=Math.max(1,r()-ie),l=Math.sqrt(o*o+c*c),p=Math.abs(c)>=Math.abs(o)?c>0?"down-scroll":"up-scroll":o>0?"right-scroll":"left-scroll",d=(null===e?ge():e.scrollHeight)||1,f=null===e?window.innerHeight||0:e.clientHeight;be(Object.assign(ve(),null===e?{}:{content_height:e.scrollHeight,scroll_offset_x:n,scroll_offset_y:a},{triggered_type:"default",gesture_type:p,gesture_duration:Math.round(u),element_label:"",triggered_id:0,coordinate_x:n,coordinate_y:a,normalized_x:0,normalized_y:me(a+f,d),velocity:Math.round(l/u*1e3),is_clickable:0,is_rage_click:0,is_dead_click:0}))}catch(e){i(s.HEATMAP,"apptics.heatmap: scroll capture failed: "+String(e))}}function trackHeatmap(status){var e="boolean"!=typeof status||status;if(e!==ne){if(e)return pe=Math.round(window.scrollX||0),de=Math.round(window.scrollY||0),window.addEventListener("pointerdown",ke,{capture:!0,passive:!0}),window.addEventListener("scroll",ye,{capture:!0,passive:!0}),ne=!0,void t.log("apptics.heatmap: capturing clicks and scrolls");window.removeEventListener("pointerdown",ke,!0),window.removeEventListener("scroll",ye,!0),null!==ce&&(clearTimeout(ce),Te()),ue=null,ne=!1,t.log("apptics.heatmap: capture stopped")}}e.trackHeatmap=trackHeatmap,e.resetHeatmap=function(){re=0,ae=[],pe=0,de=0,le=new WeakMap},e.sendHeatmaps=function e(n){return!v()&&b()&&u._heatmapTracking?0==navigator.onLine?(t.warn("sendHeatmapData: No Network"),Promise.resolve()):u._sending?(k(e),Promise.resolve()):(u._sending=!0,y(),T("heatmaps",function(){return E(A,function(){return!0},function(e){return e.triggered_time||e.session_start_time}).then(function(e){if(0!=e.length){var t=[],r=[];return H(e).forEach(function(e){r.push({...e}),delete e.id,t.push(e)}),S(function(e,t){return U("heatmap","requestToSendHeatmaps",e,t)}({data:t},n).then(function(){return A.remove(r)},function(e){return M(e)?(x("apptics: the server refused these heatmap records, so they were dropped: "+String(e&&e.message)),A.remove(r)):Promise.reject(e)}),n,"sendHeatmapData")}})}).catch(function(e){t.log("sendHeatmapData:"+e)}).then(function(){u._sending=!1})):Promise.resolve()};const Ee=C("Apptics.init",G),He=C("Apptics.ready",W),Se=C("Apptics.flush",X),Me=C("Apptics.reset",j),xe=C("Apptics.enableDebug",I),Ue=C("Apptics.disableDebug",z),De={init:function init(config){return P(Ee,arguments)},ready:function ready(){return P(He,arguments)},flush:function flush(){return P(Se,arguments)},reset:function reset(){return P(Me,arguments)},enableDebug:function enableDebug(){return P(xe,arguments)},disableDebug:function disableDebug(){return P(Ue,arguments)}},Le=C("AppticsEvent.addEvent",q),Ne={DefinedEvents:N,addEvent:function addEvent(eventName,groupName,properties){return P(Le,arguments)}},Oe=C("AppticsScreen.inScreen",B),Pe=C("AppticsScreen.outScreen",K),Ye={inScreen:function inScreen(screenName,properties){if(!Y(screenName))return Oe(screenName,properties,"",r()),"";var id=g();return Oe(screenName,properties,id,r()),id},outScreen:function outScreen(id){Pe(id,r())}},Ce=C("AppticsApi.endTrackApi",R),Ge=C("AppticsApi.startTrackApi",J),We=C("AppticsApi.configure",Q),Xe=C("AppticsApi.enableApiTracking",V),je={startTrackApi:function startTrackApi(url,method){return P(Ge,arguments)},endTrackApi:function endTrackApi(id,responseCode,responseMessage){Ce(id,responseCode,responseMessage,r())},ApiTrackingBuilder:L,configure:function configure(config){return P(We,arguments)},enableApiTracking:function enableApiTracking(enabled){return P(Xe,arguments)}},Ie=C("AppticsError.trackError",Z),ze=C("AppticsError.trackGlobalErrorHandler",$),qe={trackError:function trackError(error,properties){return P(Ie,arguments)},trackGlobalErrorHandler:function trackGlobalErrorHandler(enabled){return P(ze,arguments)}},Be=C("AppticsUser.setUser",F),Ke=C("AppticsUser.getUser",ee),Re={setUser:function setUser(userid,groupid,properties){return P(Be,arguments)},getUser:function getUser(){return P(Ke,arguments)},UserBuilder:O},Je=C("AppticsHeatmap.trackHeatmap",trackHeatmap),Qe={trackHeatmap:function trackHeatmap(on){return P(Je,arguments)}},Ve=C("AppticsSettings.setTrackingStatus",te),Ze=C("AppticsSettings.getTrackingStatus",m),$e={AP_TRACKING_STATUS:h,setTrackingStatus:function setTrackingStatus(status){return P(Ve,arguments)},getTrackingStatus:function getTrackingStatus(){return P(Ze,arguments)}},Fe={Apptics:De,AppticsEvent:Ne,AppticsScreen:Ye,AppticsApi:je,AppticsError:qe,AppticsUser:Re,AppticsSettings:$e,AppticsHeatmap:Qe};var et;et=De,"undefined"!=typeof window&&queueMicrotask(function(){!function(e){if(u._initialised)return!1;var t=D();t&&"object"==typeof t&&e.init(t)}(et)});export{De as Apptics,je as AppticsApi,qe as AppticsError,Ne as AppticsEvent,Qe as AppticsHeatmap,Ye as AppticsScreen,$e as AppticsSettings,Re as AppticsUser,Fe as default};
1
+ /*! @zoho_apptics/apptics-js-sdk v2.0.0-beta.2 | (c) Zoho Corporation Private Limited | see LICENSE */
2
+ import{C as e,y as t,n,c as r,z as a,B as i,D as s,E as c,_ as o,d as u,j as l,e as p,G as d,H as f,A as g,I as m,J as h,m as A,b as _,K as k,L as w,M as v,w as b,v as T,x as y,N as E,O as H,P as S}from"./chunks/send-CgUO82ne.min.js";import{s as M,c as x,d as U,a as D,w as C,f as L,b as N,e as O,A as P,D as j,U as G,v as Y,g as z,o as I,i as W,h as X,j as q,r as B,k as K,l as R,m as J,n as F,p as Q,t as V,q as Z,u as $,x as ee,y as te,z as ne}from"./chunks/lifecycle-C6m1W7jo.min.js";var re=!1,ae=0,ie=[],se=0,ce=0,oe=0,ue=null,le=null,pe=new WeakMap,de=0,fe=0;function ge(){var t=s("heatmap_max_per_session");return("number"!=typeof t||t<=0)&&(t=c.heatmap_max_per_session),!(ae>=t)||(ae===t&&(ae++,e.log("apptics.heatmap: reached "+t+" records for this session, pausing capture")),!1)}function me(){var e=document.documentElement,t=document.body;return Math.max(e?e.scrollHeight:0,t?t.scrollHeight:0,e?e.clientHeight:0)}function he(e,t){if(!t||t<=0)return 0;var value=e/t;return value<0&&(value=0),value>1&&(value=1),Math.round(1e3*value)/1e3}function Ae(){return window.innerWidth||(document.documentElement?document.documentElement.clientWidth:0)||1}function _e(e){if(!e)return"";for(var t=["data-ap-label","apeventaction","data-apeventaction","aria-label","name","id","title"],n=0;n<t.length;n++){var value=e.getAttribute?e.getAttribute(t[n]):null;if(!r(value))return String(value).slice(0,80)}var a=e.tagName?e.tagName.toLowerCase():"element";if(f()!==g.USAGE_TRACKING_WITH_PII){var i=e.getAttribute?e.getAttribute("role"):null;return r(i)?a:a+"["+i+"]"}var s=(e.textContent||"").replace(/\s+/g," ").trim();return r(s)?a:s.slice(0,80)}function ke(e){if(!e)return 0;for(var t="",n=e,r=0;n&&r<12;){var a=n.parentElement,i=0;if(a)for(var s=a.children,c=0;c<s.length;c++)if(s[c]===n){i=c;break}t="/"+(n.tagName||"?")+":"+i+t,n=a,r++}for(var o=2166136261,u=0;u<t.length;u++)o=16777619*(o^=t.charCodeAt(u))>>>0;return o}function we(e,t,n){return(ie=ie.filter(function(e){return n-e.at<=1e3})).push({at:n,x:e,y:t}),ie.filter(function(n){return Math.abs(n.x-e)<=30&&Math.abs(n.y-t)<=30}).length>=3}function ve(){return{id:d(),session_start_time:o._current_session.starttime||n(),triggered_time:n(),screen:String(M()).slice(0,500),url_path:String(window.location.pathname).slice(0,500),screen_width:window.screen?window.screen.width:0,screen_height:window.screen?window.screen.height:0,content_height:me(),orientation:p(),network_status:l(),edge_type:o._device_info.connectionType||u(),scroll_offset_x:Math.round(window.scrollX||window.pageXOffset||0),scroll_offset_y:Math.round(window.scrollY||window.pageYOffset||0)}}function be(t){ae++,m(),x(),h.add(t),e.dir(t)}function Te(e){if(t("heatmap")&&ge())try{var s=n(),c=e.target,o=function(e){for(var t=0;e&&t<10;){var n=e.tagName?e.tagName.toLowerCase():"",r=e.getAttribute?e.getAttribute("role"):null;if("a"===n||"button"===n||"input"===n||"select"===n||"textarea"===n||"summary"===n||"label"===n||"button"===r||"link"===r||"tab"===r||"menuitem"===r||e.hasAttribute&&e.hasAttribute("onclick"))return e;e=e.parentElement,t++}return null}(c),u=o||c,l=Math.round(e.clientX),p=Math.round(e.clientY),d=me()||1,f=e.pointerType,g=Object.assign(ve(),{triggered_type:"default",gesture_type:"click",gesture_duration:0,input_type:r(f)?"mouse":String(f),element_label:_e(u),triggered_id:ke(u),coordinate_x:l,coordinate_y:p,normalized_x:he(l,Ae()),normalized_y:he((window.scrollY||0)+p,d),velocity:0,is_clickable:o?1:0,is_rage_click:we(l,p,s)?1:0,is_dead_click:0});be(g),function(e){if(1===e.is_clickable||"function"!=typeof MutationObserver)return;var t=!1,url=window.location.href,n=new MutationObserver(function(){t=!0});try{n.observe(document.documentElement,{childList:!0,subtree:!0,attributes:!0})}catch(e){return}setTimeout(function(){n.disconnect(),t||window.location.href!==url||(e.is_dead_click=1,h.update(e))},1500)}(g)}catch(e){a(i.HEATMAP,"apptics.heatmap: click capture failed: "+String(e))}}function ye(e){if(t("heatmap")&&ge()){var r=function(e){var t=document;if(!e||1!==e.nodeType||e===t.documentElement||e===t.body)return null;var n=e;return n.clientHeight>=.5*(window.innerHeight||0)&&n.clientWidth>=.5*Ae()?n:void 0}(e?e.target:null);if(void 0!==r){if(null!==ue&&r!==le&&(clearTimeout(ue),Ee()),null===ue){le=r;var a=function(e){return null===e?{x:de,y:fe}:pe.get(e)||{x:0,y:0}}(r);se=n(),ce=a.x,oe=a.y}else clearTimeout(ue);ue=setTimeout(Ee,150)}}}function Ee(){ue=null;var e=le;le=null;try{var t=function(e){return null===e?{x:Math.round(window.scrollX||window.pageXOffset||0),y:Math.round(window.scrollY||window.pageYOffset||0)}:{x:Math.round(e.scrollLeft||0),y:Math.round(e.scrollTop||0)}}(e),r=t.x,s=t.y,c=r-ce,o=s-oe;if(null===e?(de=r,fe=s):pe.set(e,t),0===c&&0===o)return;var u=Math.max(1,n()-se),l=Math.sqrt(c*c+o*o),p=Math.abs(o)>=Math.abs(c)?o>0?"down-scroll":"up-scroll":c>0?"right-scroll":"left-scroll",d=(null===e?me():e.scrollHeight)||1,f=null===e?window.innerHeight||0:e.clientHeight;be(Object.assign(ve(),null===e?{}:{content_height:e.scrollHeight,scroll_offset_x:r,scroll_offset_y:s},{triggered_type:"default",gesture_type:p,gesture_duration:Math.round(u),element_label:"",triggered_id:0,coordinate_x:r,coordinate_y:s,normalized_x:0,normalized_y:he(s+f,d),velocity:Math.round(l/u*1e3),is_clickable:0,is_rage_click:0,is_dead_click:0}))}catch(e){a(i.HEATMAP,"apptics.heatmap: scroll capture failed: "+String(e))}}function trackHeatmap(status){var t="boolean"!=typeof status||status;if(t!==re){if(t)return de=Math.round(window.scrollX||0),fe=Math.round(window.scrollY||0),window.addEventListener("pointerdown",Te,{capture:!0,passive:!0}),window.addEventListener("scroll",ye,{capture:!0,passive:!0}),re=!0,void e.log("apptics.heatmap: capturing clicks and scrolls");window.removeEventListener("pointerdown",Te,!0),window.removeEventListener("scroll",ye,!0),null!==ue&&(clearTimeout(ue),Ee()),le=null,re=!1,e.log("apptics.heatmap: capture stopped")}}A.trackHeatmap=trackHeatmap,A.resetHeatmap=function(){ae=0,ie=[],de=0,fe=0,pe=new WeakMap},A.sendHeatmaps=function t(n){return!_()&&k()&&o._heatmapTracking?0==navigator.onLine?(e.warn("sendHeatmapData: No Network"),Promise.resolve()):o._sending?(U(t),Promise.resolve()):(o._sending=!0,D(),C("heatmaps",function(){return L(h,function(){return!0},function(e){return e.triggered_time||e.session_start_time}).then(function(e){if(0!=e.length){var t=[],r=[];return w(e).forEach(function(e){r.push({...e}),delete e.id,t.push(e)}),N(function(e,t){return O("heatmap","requestToSendHeatmaps",e,t)}({data:t},n).then(function(){return h.remove(r)},function(e){return v(e)?(b("apptics: the server refused these heatmap records, so they were dropped: "+String(e&&e.message)),h.remove(r)):Promise.reject(e)}),n,"sendHeatmapData")}})}).catch(function(t){e.log("sendHeatmapData:"+t)}).then(function(){o._sending=!1})):Promise.resolve()};const He=y("Apptics.init",K),Se=y("Apptics.ready",B),Me=y("Apptics.flush",q),xe=y("Apptics.reset",X),Ue=y("Apptics.enableDebug",H),De=y("Apptics.disableDebug",E);var Ce={};function Le(e,t){Ce[e]||(Ce[e]=!0,b(e+" is now "+t+"; rename it in your code"))}const Ne={init:function init(config){return T(He,arguments)},ready:function ready(){return T(Se,arguments)},flush:function flush(){return T(Me,arguments)},reset:function reset(){return T(xe,arguments)},enableDebug:function enableDebug(){return T(Ue,arguments)},disableDebug:function disableDebug(){return T(De,arguments)}},Oe=y("AppticsEvent.addEvent",$),Pe=y("AppticsEvent.setClickTracking",Z),je={DefinedEvents:j,addEvent:function addEvent(eventName,groupName,properties){return T(Oe,arguments)},setClickTracking:function setClickTracking(enabled){return T(Pe,arguments)}},Ge=y("AppticsScreen.inScreen",W),Ye=y("AppticsScreen.outScreen",I),ze=y("AppticsScreen.setScreenTracking",ee),Ie={inScreen:function inScreen(screenName,properties){if(!Y(screenName))return Ge(screenName,properties,"",n()),"";var id=d();return Ge(screenName,properties,id,n()),id},outScreen:function outScreen(id){Ye(id,n())},setScreenTracking:function setScreenTracking(enabled){return T(ze,arguments)}},We=y("AppticsApi.endTrackApi",z),Xe=y("AppticsApi.startTrackApi",F),qe=y("AppticsApi.configure",J),Be=y("AppticsApi.setApiTracking",R),Ke={startTrackApi:function startTrackApi(url,method){return T(Xe,arguments)},endTrackApi:function endTrackApi(id,responseCode,responseMessage){We(id,responseCode,responseMessage,n())},ApiTrackingBuilder:P,configure:function configure(config){return T(qe,arguments)},setApiTracking:function setApiTracking(enabled){return T(Be,arguments)},enableApiTracking:function enableApiTracking(enabled){return Le("AppticsApi.enableApiTracking","AppticsApi.setApiTracking"),T(Be,arguments)}},Re=y("AppticsError.trackError",V),Je=y("AppticsError.setErrorTracking",Q),Fe={trackError:function trackError(error,properties){return T(Re,arguments)},setErrorTracking:function setErrorTracking(enabled){return T(Je,arguments)},trackGlobalErrorHandler:function trackGlobalErrorHandler(enabled){return Le("AppticsError.trackGlobalErrorHandler","AppticsError.setErrorTracking"),T(Je,arguments)}},Qe=y("AppticsUser.setUser",ne),Ve=y("AppticsUser.getUser",te),Ze={setUser:function setUser(userid,groupid,properties){return T(Qe,arguments)},getUser:function getUser(){return T(Ve,arguments)},UserBuilder:G},$e=y("AppticsHeatmap.setHeatmapTracking",trackHeatmap),et={setHeatmapTracking:function setHeatmapTracking(enabled){return T($e,arguments)},trackHeatmap:function trackHeatmap(on){return Le("AppticsHeatmap.trackHeatmap","AppticsHeatmap.setHeatmapTracking"),T($e,arguments)}},tt=y("AppticsSettings.setTrackingStatus",S),nt=y("AppticsSettings.getTrackingStatus",f),rt={AP_TRACKING_STATUS:g,setTrackingStatus:function setTrackingStatus(status){return T(tt,arguments)},getTrackingStatus:function getTrackingStatus(){return T(nt,arguments)}},at={Apptics:Ne,AppticsEvent:je,AppticsScreen:Ie,AppticsApi:Ke,AppticsError:Fe,AppticsUser:Ze,AppticsSettings:rt,AppticsHeatmap:et};export{Ne as Apptics,Ke as AppticsApi,Fe as AppticsError,je as AppticsEvent,et as AppticsHeatmap,Ie as AppticsScreen,rt as AppticsSettings,Ze as AppticsUser,at as default};
3
3
  //# sourceMappingURL=apptics.esm.min.js.map