@hellotext/hellotext 1.0.8 → 1.0.10
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 +44 -8
- package/lib/errors/notInitializedError.js +4 -2
- package/lib/hellotext.js +32 -31
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
# Hellotext.js
|
|
2
2
|
|
|
3
|
-
[](https://badge.fury.io/js/@hellotext%2Fhellotext)
|
|
4
|
-
|
|
5
3
|
Track the events happening on your site to [Hellotext](https://www.hellotext.com) in real-time with this library.
|
|
6
4
|
|
|
7
5
|
## Installation
|
|
@@ -44,10 +42,44 @@ Tracking events is straightforward and perhaps the simplest example is tracking
|
|
|
44
42
|
Hellotext.track("page.viewed");
|
|
45
43
|
```
|
|
46
44
|
|
|
47
|
-
In the example above only the name of the action is required.
|
|
45
|
+
In the example above only the name of the action is required.
|
|
48
46
|
The library takes care of handling the `url` parameter with the current URL automatically and is not required to specify it explicitly.
|
|
49
|
-
|
|
47
|
+
If you want to provide another url, you can pass a `url` key in the params object when tracking an event.
|
|
48
|
+
|
|
49
|
+
```javascript
|
|
50
|
+
Hellotext.track("page.viewed", {
|
|
51
|
+
url: "www.example.org"
|
|
52
|
+
});
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
The `track` method returns a Promise that can be `await`ed using the async/await syntax. Or using `.then` on the returned Promise
|
|
56
|
+
|
|
57
|
+
```javascript
|
|
58
|
+
const response = await Hellotext.track("page.viewed");
|
|
59
|
+
// {status: "received", success: true}
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
The parameters passed to the action must be a valid set of parameters as described in
|
|
63
|
+
[Tracking Actions](https://www.hellotext.com/api#tracking).
|
|
64
|
+
|
|
65
|
+
Failing to provide valid set of parameters will result in an error object being returned, describing the parameters that did not satisfy the rules.
|
|
66
|
+
|
|
67
|
+
```javascript
|
|
68
|
+
const response = await Hellotext.track("app.installed", { app_attributes: { name: "My App" }})
|
|
69
|
+
{
|
|
70
|
+
errors: [
|
|
71
|
+
{
|
|
72
|
+
type: 'parameter_not_unique',
|
|
73
|
+
parameter: 'name',
|
|
74
|
+
description: 'The value must be unique and it is already present in another object of the same type.'
|
|
75
|
+
},
|
|
76
|
+
],
|
|
77
|
+
success: false
|
|
78
|
+
}
|
|
79
|
+
```
|
|
50
80
|
|
|
81
|
+
You can use `success` key present in the response object to run code conditionally.
|
|
82
|
+
For a complete list of errors types. See [Error Types](https://www.hellotext.com/api#errors)
|
|
51
83
|
|
|
52
84
|
Generally, most actions also require an associated object. These can be of type [`app`](https://www.hellotext.com/api#apps), [`coupon`](https://www.hellotext.com/api#coupons), [`form`](https://www.hellotext.com/api#forms), [`order`](https://www.hellotext.com/api#orders), [`product`](https://www.hellotext.com/api#products) and [`refund`](https://www.hellotext.com/api#refunds).
|
|
53
85
|
|
|
@@ -119,7 +151,7 @@ Hellotext.track("product.purchased", {
|
|
|
119
151
|
|
|
120
152
|
| Property | Description | Type | Default |
|
|
121
153
|
| --- | --- | --- | --- |
|
|
122
|
-
| **amount** | Monetary amount that represents the revenue associated to this tracked event. | float | `
|
|
154
|
+
| **amount** | Monetary amount that represents the revenue associated to this tracked event. | float | `0`
|
|
123
155
|
| **currency** | Currency for the `amount` given in ISO 4217 format. | currency | `USD`
|
|
124
156
|
| **metadata** | Set of key-value pairs that you can attach to an event. This can be useful for storing additional information about the object in a structured format. | hash | `{}`
|
|
125
157
|
| **tracked_at** | Original date when the event happened. This is useful if you want to record an event that happened in the past. If no value is provided its value will be the same from `created_at`. | epoch | `null`
|
|
@@ -127,17 +159,21 @@ Hellotext.track("product.purchased", {
|
|
|
127
159
|
|
|
128
160
|
## Understanding Sessions
|
|
129
161
|
|
|
130
|
-
The library looks for a session identifier present on the `hellotext_session` parameter. If the session is not present as a cookie neither it will create a new random session identifier.
|
|
162
|
+
The library looks for a session identifier present on the `hellotext_session` query parameter. If the session is not present as a cookie neither it will create a new random session identifier.
|
|
163
|
+
The session is automatically sent to Hellotext any time the `Hellotext.track` method is called.
|
|
131
164
|
|
|
132
|
-
Short links redirections attaches a session identifier to the destination url as `hellotext_session` parameter. This will identify all the events back to the customer who opened the link.
|
|
165
|
+
Short links redirections attaches a session identifier to the destination url as `hellotext_session` query parameter. This will identify all the events back to the customer who opened the link.
|
|
133
166
|
|
|
134
167
|
### Get session
|
|
135
168
|
|
|
136
169
|
It is possible to obtain the current session by simply calling `Hellotext.session`.
|
|
137
170
|
|
|
138
171
|
```javascript
|
|
139
|
-
Hellotext.session
|
|
172
|
+
await Hellotext.session
|
|
140
173
|
// Returns bBJn9vR15yPaYkWmR2QK0jopMeNxrA6l
|
|
141
174
|
```
|
|
175
|
+
Calling the `Hellotext.session` for the first time will send a request to Hellotext to create a session,
|
|
176
|
+
then the class stores the value in the `hello_session` cookie. Subsequent calls would not result in requests made to the server,
|
|
177
|
+
because the class stores the value.
|
|
142
178
|
|
|
143
179
|
You may want to store the session on your backend when customers are unidentified so you can later [attach it to a profile](https://www.hellotext.com/api#attach_session) when it becomes known.
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
class NotInitializedError extends Error {
|
|
2
2
|
constructor() {
|
|
3
|
-
super(
|
|
4
|
-
|
|
3
|
+
super(
|
|
4
|
+
'You need to initialize before tracking events. Call Hellotext.initialize and pass your public business id',
|
|
5
|
+
)
|
|
6
|
+
this.name = 'NotInitializedError'
|
|
5
7
|
}
|
|
6
8
|
}
|
|
7
9
|
|
package/lib/hellotext.js
CHANGED
|
@@ -1,25 +1,22 @@
|
|
|
1
|
-
import { NotInitializedError } from
|
|
1
|
+
import { NotInitializedError } from './errors/notInitializedError'
|
|
2
2
|
|
|
3
3
|
const apiUrl = 'https://api.hellotext.com/v1/'
|
|
4
4
|
|
|
5
5
|
class Hellotext {
|
|
6
|
+
static #_session
|
|
7
|
+
static #business_id
|
|
6
8
|
/**
|
|
7
9
|
* initialize the module.
|
|
8
10
|
*/
|
|
9
11
|
static initialize(business_id) {
|
|
10
|
-
this
|
|
12
|
+
this.#business_id = business_id
|
|
11
13
|
|
|
12
14
|
const urlSearchParams = new URLSearchParams(window.location.search)
|
|
13
15
|
const session = urlSearchParams.get('hello_session') || getCookieValue('hello_session')
|
|
14
16
|
|
|
15
17
|
if (session) {
|
|
16
|
-
this
|
|
18
|
+
this.#_session = session
|
|
17
19
|
this.setSessionCookie(session)
|
|
18
|
-
} else {
|
|
19
|
-
this.mintAnonymousSession().then(response => {
|
|
20
|
-
this._session = response.id
|
|
21
|
-
this.setSessionCookie(response.id)
|
|
22
|
-
})
|
|
23
20
|
}
|
|
24
21
|
}
|
|
25
22
|
|
|
@@ -27,24 +24,26 @@ class Hellotext {
|
|
|
27
24
|
*
|
|
28
25
|
* @param { String } action a valid action name
|
|
29
26
|
* @param { Object } params
|
|
30
|
-
* @param { String } url optional url, the url is automatically inferred when the action is tracked
|
|
31
27
|
* @returns {Promise}
|
|
32
28
|
*/
|
|
33
|
-
static async track(action, params
|
|
34
|
-
if(this.notInitialized) { throw new NotInitializedError() }
|
|
29
|
+
static async track(action, params) {
|
|
30
|
+
if (this.notInitialized) { throw new NotInitializedError() }
|
|
35
31
|
|
|
36
|
-
const response = await fetch(apiUrl +
|
|
32
|
+
const response = await fetch(apiUrl + 'track/events', {
|
|
37
33
|
headers: this.headers,
|
|
38
|
-
method:
|
|
34
|
+
method: 'post',
|
|
39
35
|
body: JSON.stringify({
|
|
40
|
-
session: this.session,
|
|
41
|
-
url: url || window.location.href,
|
|
36
|
+
session: await this.session,
|
|
42
37
|
action,
|
|
43
38
|
...params,
|
|
44
|
-
|
|
39
|
+
url: (params && params.url) || window.location.href
|
|
40
|
+
}),
|
|
45
41
|
})
|
|
46
42
|
|
|
47
|
-
|
|
43
|
+
const body = await response.json()
|
|
44
|
+
body.success = response.status === 200
|
|
45
|
+
|
|
46
|
+
return body
|
|
48
47
|
}
|
|
49
48
|
|
|
50
49
|
/**
|
|
@@ -52,49 +51,51 @@ class Hellotext {
|
|
|
52
51
|
* @returns {Promise<any>|String}
|
|
53
52
|
*/
|
|
54
53
|
static get session() {
|
|
55
|
-
if(this.notInitialized) { throw new NotInitializedError() }
|
|
54
|
+
if (this.notInitialized) { throw new NotInitializedError() }
|
|
56
55
|
|
|
57
|
-
if (this
|
|
56
|
+
if (this.#_session) return this.#_session
|
|
58
57
|
|
|
59
|
-
return this.mintAnonymousSession()
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
58
|
+
return this.mintAnonymousSession()
|
|
59
|
+
.then(response => {
|
|
60
|
+
this.#_session = response.id
|
|
61
|
+
this.setSessionCookie(response.id)
|
|
62
|
+
})
|
|
63
|
+
.then(() => this.#_session)
|
|
63
64
|
}
|
|
64
65
|
|
|
65
66
|
// private
|
|
66
67
|
|
|
67
68
|
static async mintAnonymousSession() {
|
|
68
|
-
if(this.notInitialized) { throw new NotInitializedError() }
|
|
69
|
+
if (this.notInitialized) { throw new NotInitializedError() }
|
|
69
70
|
|
|
70
71
|
const trackingUrl = apiUrl + 'track/sessions'
|
|
71
72
|
|
|
72
73
|
this.mintingPromise = await fetch(trackingUrl, {
|
|
73
|
-
method:
|
|
74
|
-
headers: { Authorization: `Bearer ${this
|
|
74
|
+
method: 'post',
|
|
75
|
+
headers: { Authorization: `Bearer ${this.#business_id}` },
|
|
75
76
|
})
|
|
76
77
|
|
|
77
78
|
return this.mintingPromise.json()
|
|
78
79
|
}
|
|
79
80
|
|
|
80
81
|
static get headers() {
|
|
81
|
-
if(this.notInitialized) { throw new NotInitializedError() }
|
|
82
|
+
if (this.notInitialized) { throw new NotInitializedError() }
|
|
82
83
|
|
|
83
84
|
return {
|
|
84
|
-
Authorization: `Bearer ${this
|
|
85
|
+
Authorization: `Bearer ${this.#business_id}`,
|
|
85
86
|
Accept: 'application.json',
|
|
86
|
-
'Content-Type': 'application/json'
|
|
87
|
+
'Content-Type': 'application/json',
|
|
87
88
|
}
|
|
88
89
|
}
|
|
89
90
|
|
|
90
91
|
static setSessionCookie(session) {
|
|
91
|
-
if(this.notInitialized) { throw new NotInitializedError() }
|
|
92
|
+
if (this.notInitialized) { throw new NotInitializedError() }
|
|
92
93
|
|
|
93
94
|
document.cookie = `hello_session=${session}`
|
|
94
95
|
}
|
|
95
96
|
|
|
96
97
|
static get notInitialized() {
|
|
97
|
-
return this
|
|
98
|
+
return this.#business_id === undefined
|
|
98
99
|
}
|
|
99
100
|
}
|
|
100
101
|
|