cb-cookie-manager 0.0.1-security → 1.0.0
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.
Potentially problematic release.
This version of cb-cookie-manager might be problematic. Click here for more details.
- package/.eslintignore +11 -0
- package/LICENSE.md +13 -0
- package/README.md +477 -3
- package/dist/CookieContext.d.ts +10 -0
- package/dist/CookieContext.js +182 -0
- package/dist/TrackingManagerContext.d.ts +6 -0
- package/dist/TrackingManagerContext.js +53 -0
- package/dist/analytics.js +119 -0
- package/dist/constants.d.ts +11 -0
- package/dist/constants.js +32 -0
- package/dist/examples/config.d.ts +28 -0
- package/dist/examples/config.js +77 -0
- package/dist/hooks/useHasConsent.d.ts +2 -0
- package/dist/hooks/useHasConsent.js +14 -0
- package/dist/hooks/useRequiredCategories.d.ts +3 -0
- package/dist/hooks/useRequiredCategories.js +10 -0
- package/dist/hooks/useSavedTrackingPreference.d.ts +3 -0
- package/dist/hooks/useSavedTrackingPreference.js +38 -0
- package/dist/hooks/useSetTrackingPreference.d.ts +3 -0
- package/dist/hooks/useSetTrackingPreference.js +27 -0
- package/dist/hooks/useTrackingPreference.d.ts +3 -0
- package/dist/hooks/useTrackingPreference.js +16 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.js +39 -0
- package/dist/types.d.ts +62 -0
- package/dist/types.js +28 -0
- package/dist/utils/areCookiesEnabled.d.ts +2 -0
- package/dist/utils/areCookiesEnabled.js +14 -0
- package/dist/utils/getAllCookies.d.ts +3 -0
- package/dist/utils/getAllCookies.js +64 -0
- package/dist/utils/getDefaultTrackingPreference.d.ts +3 -0
- package/dist/utils/getDefaultTrackingPreference.js +28 -0
- package/dist/utils/getDomain.d.ts +2 -0
- package/dist/utils/getDomain.js +21 -0
- package/dist/utils/getTrackerCategory.d.ts +3 -0
- package/dist/utils/getTrackerCategory.js +11 -0
- package/dist/utils/getTrackerInfo.d.ts +3 -0
- package/dist/utils/getTrackerInfo.js +12 -0
- package/dist/utils/hasConsent.d.ts +11 -0
- package/dist/utils/hasConsent.js +29 -0
- package/dist/utils/isMaxKBSize.d.ts +2 -0
- package/dist/utils/isMaxKBSize.js +7 -0
- package/dist/utils/isOptOut.d.ts +16 -0
- package/dist/utils/isOptOut.js +25 -0
- package/dist/utils/persistMobileAppPreferences.d.ts +2 -0
- package/dist/utils/persistMobileAppPreferences.js +36 -0
- package/dist/utils/setGTMVariables.d.ts +3 -0
- package/dist/utils/setGTMVariables.js +14 -0
- package/dist/utils/setTrackingPreference.d.ts +4 -0
- package/dist/utils/setTrackingPreference.js +22 -0
- package/dist/utils/trackerMatches.d.ts +3 -0
- package/dist/utils/trackerMatches.js +12 -0
- package/jest.config.ts +204 -0
- package/package.json +30 -3
- package/src/CookieContext.test.tsx +105 -0
- package/src/CookieContext.tsx +215 -0
- package/src/TrackingManagerContext.tsx +25 -0
- package/src/analytics.ts +65 -0
- package/src/constants.ts +35 -0
- package/src/examples/config.ts +76 -0
- package/src/global.d.ts +3 -0
- package/src/hooks/useHasConsent.ts +11 -0
- package/src/hooks/useRequiredCaregories.test.tsx +43 -0
- package/src/hooks/useRequiredCategories.ts +11 -0
- package/src/hooks/useSavedTrackingPreference.ts +47 -0
- package/src/hooks/useSetTrackingPreference.test.tsx +82 -0
- package/src/hooks/useSetTrackingPreference.ts +31 -0
- package/src/hooks/useTrackingPreference.ts +15 -0
- package/src/index.ts +20 -0
- package/src/types.ts +71 -0
- package/src/utils/areCookiesEnabled.ts +13 -0
- package/src/utils/getAllCookies.test.ts +35 -0
- package/src/utils/getAllCookies.ts +68 -0
- package/src/utils/getDefaultTrackingPreference.test.ts +16 -0
- package/src/utils/getDefaultTrackingPreference.ts +28 -0
- package/src/utils/getDomain.test.ts +16 -0
- package/src/utils/getDomain.ts +19 -0
- package/src/utils/getTrackerCategory.test.ts +34 -0
- package/src/utils/getTrackerCategory.ts +11 -0
- package/src/utils/getTrackerInfo.test.ts +11 -0
- package/src/utils/getTrackerInfo.ts +10 -0
- package/src/utils/hasConsent.test.ts +64 -0
- package/src/utils/hasConsent.ts +32 -0
- package/src/utils/isMaxKBSize.test.ts +10 -0
- package/src/utils/isMaxKBSize.ts +7 -0
- package/src/utils/isOptOut.test.ts +14 -0
- package/src/utils/isOptOut.ts +28 -0
- package/src/utils/persistMobileAppPreferences.ts +32 -0
- package/src/utils/setGTMVariables.test.ts +20 -0
- package/src/utils/setGTMVariables.ts +17 -0
- package/src/utils/setTrackingPreference.ts +36 -0
- package/src/utils/trackerMatches.test.ts +13 -0
- package/src/utils/trackerMatches.ts +12 -0
- package/tsconfig.json +112 -0
package/.eslintignore
ADDED
package/LICENSE.md
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
Copyright (c) 2018-2023 Coinbase, Inc.
|
|
2
|
+
|
|
3
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
you may not use this file except in compliance with the License.
|
|
5
|
+
You may obtain a copy of the License at
|
|
6
|
+
|
|
7
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
|
|
9
|
+
Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
See the License for the specific language governing permissions and
|
|
13
|
+
limitations under the License.
|
package/README.md
CHANGED
|
@@ -1,5 +1,479 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Cookie Manager
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
**Helps with managaing first-party client side cookies to adhere to CCPA and GDPR Cookie regulations**
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
# Contents
|
|
6
|
+
|
|
7
|
+
- [Introduction](#Introduction)
|
|
8
|
+
- [Installation](#installation)
|
|
9
|
+
- [Methods](#methods)
|
|
10
|
+
- [Provider](#provider)
|
|
11
|
+
- [useCookie](#usecookie)
|
|
12
|
+
- [useHasConsent](#usehasconsent)
|
|
13
|
+
- [useRequiredCategories](#userequiredcategories)
|
|
14
|
+
- [useSavedTrackingPreference](#usesavedtrackingpreference)
|
|
15
|
+
- [useSetTrackingPreference](#usesettrackingpreference)
|
|
16
|
+
- [useTrackingPreference](#usesettrackingpreference)
|
|
17
|
+
- [areCookiesEnabled](#arecookiesenabled)
|
|
18
|
+
- [getDefaultTrackingPreference](#getdefaulttrackingpreference)
|
|
19
|
+
- [useTrackingManager](#usetrackingmanager)
|
|
20
|
+
- [isOptOut](#isoptout)
|
|
21
|
+
- [License](#license)
|
|
22
|
+
|
|
23
|
+
## Introduction
|
|
24
|
+
|
|
25
|
+
`cb-cookie-manager` helps manage the following first party client side cookie categories:
|
|
26
|
+
|
|
27
|
+
- `Necessary Cookies`: Cookies that are necessary for the site to the function
|
|
28
|
+
- `Performance Cookies`: Cookies that impact site performance and help mesaure performance
|
|
29
|
+
- `Functional Cookies`: Cookies to improve the functionality of the site
|
|
30
|
+
- `Targeting Cookies`: Cookies used for advertising and ad targeting
|
|
31
|
+
|
|
32
|
+
The preferences is stored as `cm_eu_preference` cookie in case the user is from EU or as `cm_default_preference` cookie in any other case
|
|
33
|
+
|
|
34
|
+
A `cm_default_preference` cookie looks like the following:
|
|
35
|
+
|
|
36
|
+
```json
|
|
37
|
+
{
|
|
38
|
+
"region": "DEFAULT",
|
|
39
|
+
"consent": ["necessary", "performance", "functional", "targeting"]
|
|
40
|
+
}
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
Where region is `DEFAULT` and consent specifies what types of cookie categories the user has given preference too. This is stored as a strictly necessary cookie and has an expiration duration of 1 year.
|
|
44
|
+
|
|
45
|
+
Cookie Manager accepts a config like this:
|
|
46
|
+
|
|
47
|
+
```typescript
|
|
48
|
+
import {
|
|
49
|
+
Framework,
|
|
50
|
+
Region,
|
|
51
|
+
TrackerType,
|
|
52
|
+
TrackingCategory,
|
|
53
|
+
} from 'cb-cookie-manager';
|
|
54
|
+
|
|
55
|
+
export default {
|
|
56
|
+
categories: [
|
|
57
|
+
{
|
|
58
|
+
id: TrackingCategory.NECESSARY,
|
|
59
|
+
required: true,
|
|
60
|
+
trackers: [
|
|
61
|
+
{
|
|
62
|
+
id: 'locale',
|
|
63
|
+
type: TrackerType.COOKIE,
|
|
64
|
+
},
|
|
65
|
+
],
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
id: TrackingCategory.PERFORMANCE,
|
|
69
|
+
trackers: [
|
|
70
|
+
{
|
|
71
|
+
id: 'some_cookie',
|
|
72
|
+
type: TrackerType.COOKIE,
|
|
73
|
+
},
|
|
74
|
+
],
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
id: TrackingCategory.FUNCTIONAL,
|
|
78
|
+
trackers: [
|
|
79
|
+
{
|
|
80
|
+
id: 'mode',
|
|
81
|
+
type: TrackerType.COOKIE,
|
|
82
|
+
},
|
|
83
|
+
],
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
id: TrackingCategory.TARGETING,
|
|
87
|
+
trackers: [
|
|
88
|
+
{
|
|
89
|
+
id: 'id-regex',
|
|
90
|
+
type: TrackerType.COOKIE,
|
|
91
|
+
regex: 'id(?:_[a-f0-9]{32}|undefined)(?:.*)',
|
|
92
|
+
},
|
|
93
|
+
],
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
id: TrackingCategory.DELETE_IF_SEEN,
|
|
97
|
+
trackers: [
|
|
98
|
+
{
|
|
99
|
+
id: 'cgl_prog',
|
|
100
|
+
type: TrackerType.COOKIE,
|
|
101
|
+
},
|
|
102
|
+
],
|
|
103
|
+
},
|
|
104
|
+
],
|
|
105
|
+
geolocationRules: [
|
|
106
|
+
{
|
|
107
|
+
region: Region.DEFAULT,
|
|
108
|
+
framework: Framework.OPT_OUT,
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
region: Region.EU,
|
|
112
|
+
framework: Framework.OPT_IN,
|
|
113
|
+
},
|
|
114
|
+
],
|
|
115
|
+
};
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
In this config, under each category you can specify what all cookies should be allowed. Everything else, if detected will be deleted at an interval of 500 ms.
|
|
119
|
+
|
|
120
|
+
`DELETE_IF_SEEN` can be used to specify the cookies which should be deleted if seen on the browser
|
|
121
|
+
|
|
122
|
+
You can also specify regex for a given cookie as follows:
|
|
123
|
+
|
|
124
|
+
```json
|
|
125
|
+
{
|
|
126
|
+
id: 'id-regex',
|
|
127
|
+
type: TrackerType.COOKIE,
|
|
128
|
+
regex: 'id(?:_[a-f0-9]{32}|undefined)(?:.*)',
|
|
129
|
+
}
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
Any id with `-regex` at the end should contain a `regex` which will be used to match different cookies.
|
|
133
|
+
|
|
134
|
+
In this example: `id_ac7a5c3da45e3612b44543a702e42b01` will also be allowed
|
|
135
|
+
|
|
136
|
+
## Installation
|
|
137
|
+
|
|
138
|
+
Install the package as follows:
|
|
139
|
+
|
|
140
|
+
```shell
|
|
141
|
+
yarn add cb-cookie-manager
|
|
142
|
+
|
|
143
|
+
npm install cb-cookie-manager
|
|
144
|
+
|
|
145
|
+
pnpm install cb-cookie-manager
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
## Methods
|
|
149
|
+
|
|
150
|
+
### Provider
|
|
151
|
+
|
|
152
|
+
The provider must wrap the entire application and only be instantiated once. On mount, it will remove all blocked cookies (i.e. cookies that do not have user consent). It takes the following props:
|
|
153
|
+
|
|
154
|
+
`onError: (error: Error) => void`: Error function
|
|
155
|
+
|
|
156
|
+
`projectName: string`: Current project name
|
|
157
|
+
|
|
158
|
+
`locale: string`: Locale to be displayed
|
|
159
|
+
|
|
160
|
+
`region: 'EU' | 'DEFAULT'`; `DEFAULT` refers to non-EU countries
|
|
161
|
+
|
|
162
|
+
`onPreferenceChange?: (preference: TrackingPreference) => void`: Callback for when user consent preferences change. This will also be called on mount.
|
|
163
|
+
|
|
164
|
+
`config: Config`: Cookie manager config. See [Config](#config) section below
|
|
165
|
+
|
|
166
|
+
`shadowMode?: boolean`: Cookies will not be removed in this mode
|
|
167
|
+
|
|
168
|
+
`log: (str: string, options?: Record<string, any>) => void`: Log function
|
|
169
|
+
|
|
170
|
+
Example usage:
|
|
171
|
+
|
|
172
|
+
```typescript
|
|
173
|
+
import { Provider, Region, TrackingCategory, TrackingPreference } from 'cb-cookie-manager';
|
|
174
|
+
|
|
175
|
+
<Provider
|
|
176
|
+
onError={notifyError}
|
|
177
|
+
onPreferenceChange={() => {}}
|
|
178
|
+
locale={localeCode}
|
|
179
|
+
region={isInEU(locale.country) ? Region.EU : Region.Default}
|
|
180
|
+
projectName="consumer-marketing"
|
|
181
|
+
config={cookieManagerConfig}
|
|
182
|
+
log={eventTracking.track}
|
|
183
|
+
shadowMode
|
|
184
|
+
>
|
|
185
|
+
{children}
|
|
186
|
+
</Provider>
|
|
187
|
+
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
### useCookie
|
|
191
|
+
|
|
192
|
+
You should replace all usages of setting, removing or getting cookies with the `useCookie` hook. The cookie manager will prevent any non-consented cookies from being set. Passing `undefined` or `null` to the set cookie function will remove that cookie. You can also pass optional parameters to change the cookie properties.
|
|
193
|
+
|
|
194
|
+
It accepts the following props:
|
|
195
|
+
|
|
196
|
+
```
|
|
197
|
+
`cookieName`: Name of the cookie for which you want to perform operations
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
`useCookie` returns the current `cookie` value and a `setCookieFunction`
|
|
201
|
+
|
|
202
|
+
`setCookieFunction` can take in the following props:
|
|
203
|
+
|
|
204
|
+
- `value`: The value to be set for the cookie
|
|
205
|
+
- `CookieAttributes`: This is optional but you can specify the following properties for a cookie:
|
|
206
|
+
|
|
207
|
+
```typescript
|
|
208
|
+
interface CookieAttributes {
|
|
209
|
+
/**
|
|
210
|
+
* Define when the cookie will be removed. Value can be a Number
|
|
211
|
+
* which will be interpreted as days from time of creation or a
|
|
212
|
+
* Date instance. If omitted, the cookie becomes a session cookie.
|
|
213
|
+
*/
|
|
214
|
+
expires?: number | Date;
|
|
215
|
+
|
|
216
|
+
/**
|
|
217
|
+
* Define the path where the cookie is available. Defaults to '/'
|
|
218
|
+
*/
|
|
219
|
+
path?: string;
|
|
220
|
+
|
|
221
|
+
/**
|
|
222
|
+
* Define the domain where the cookie is available. Defaults to
|
|
223
|
+
* the domain of the page where the cookie was created.
|
|
224
|
+
*/
|
|
225
|
+
domain?: string;
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* A Boolean indicating if the cookie transmission requires a
|
|
229
|
+
* secure protocol (https). Defaults to false.
|
|
230
|
+
*/
|
|
231
|
+
secure?: boolean;
|
|
232
|
+
|
|
233
|
+
/**
|
|
234
|
+
* Asserts that a cookie must not be sent with cross-origin requests,
|
|
235
|
+
* providing some protection against cross-site request forgery
|
|
236
|
+
* attacks (CSRF)
|
|
237
|
+
*/
|
|
238
|
+
sameSite?: 'strict' | 'lax' | 'none';
|
|
239
|
+
|
|
240
|
+
/**
|
|
241
|
+
* An attribute which will be serialized, conformably to RFC 6265
|
|
242
|
+
* section 5.2.
|
|
243
|
+
*/
|
|
244
|
+
[property: string]: any;
|
|
245
|
+
}
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
Example usage:
|
|
249
|
+
|
|
250
|
+
```typescript
|
|
251
|
+
import { useCookie } from '@cb/cookie-manager';
|
|
252
|
+
|
|
253
|
+
const SomeComponent = () => {
|
|
254
|
+
const [cookie, setCookie] = useCookie('some_cookie');
|
|
255
|
+
const handleClick = () => {
|
|
256
|
+
setCookie('hello')
|
|
257
|
+
};
|
|
258
|
+
|
|
259
|
+
return (
|
|
260
|
+
<div>
|
|
261
|
+
<button onClick={handleClick}>Set cookie</button>
|
|
262
|
+
<span>Current cookie: </span>
|
|
263
|
+
<span>{cookie}</span>
|
|
264
|
+
</div>
|
|
265
|
+
}
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
### useHasConsent
|
|
269
|
+
|
|
270
|
+
This is a hook for programmatically determining if a tracker (e.g. cookie) has been consented to by the user.
|
|
271
|
+
|
|
272
|
+
```typescript
|
|
273
|
+
import { useHasConsent } from 'cb-cookie-manager';
|
|
274
|
+
|
|
275
|
+
const SomeComponent = () => {
|
|
276
|
+
const hasConsent = useHasConsent('cookie');
|
|
277
|
+
|
|
278
|
+
return (
|
|
279
|
+
<div>
|
|
280
|
+
{hasConsent && <div> Cookie has consent </div>
|
|
281
|
+
</div>
|
|
282
|
+
}
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
### useRequiredCategories
|
|
286
|
+
|
|
287
|
+
This hook is used to determine which category of cookies is required.
|
|
288
|
+
|
|
289
|
+
Example Usage:
|
|
290
|
+
|
|
291
|
+
```typescript
|
|
292
|
+
import { useRequiredCategories, TRACKER_CATEGORIES } from 'cb-cookie-manager';
|
|
293
|
+
|
|
294
|
+
const SomeComponent = () => {
|
|
295
|
+
const requiredCategories = useRequiredCategories();
|
|
296
|
+
|
|
297
|
+
return (
|
|
298
|
+
<div>
|
|
299
|
+
<CategoryContainer>
|
|
300
|
+
{TRACKER_CATEGORIES.map(t => (
|
|
301
|
+
<CheckBoxContainer key={t}>
|
|
302
|
+
<CheckBox
|
|
303
|
+
disabled={requiredCategories.includes(t)}
|
|
304
|
+
checked={state.consent.includes(t)}
|
|
305
|
+
onChange={(val: boolean) => dispatch({ name: t, value: val })}
|
|
306
|
+
>
|
|
307
|
+
<CategoryLabel name={t} />
|
|
308
|
+
</CheckBox>
|
|
309
|
+
</CheckBoxContainer>
|
|
310
|
+
))}
|
|
311
|
+
</CategoryContainer>
|
|
312
|
+
</div>
|
|
313
|
+
}
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
### useSavedTrackingPreference
|
|
317
|
+
|
|
318
|
+
This hook is used to retrieve the saved cookie preference in cache
|
|
319
|
+
|
|
320
|
+
Example Usage:
|
|
321
|
+
|
|
322
|
+
```typescript
|
|
323
|
+
import { useSavedTrackingPreference } from 'cb-cookie-manager';
|
|
324
|
+
|
|
325
|
+
const SomeComponent = () => {
|
|
326
|
+
const preference = useSavedTrackingPreference();
|
|
327
|
+
|
|
328
|
+
return (
|
|
329
|
+
<div>
|
|
330
|
+
{preference}
|
|
331
|
+
</div>
|
|
332
|
+
)
|
|
333
|
+
}
|
|
334
|
+
```
|
|
335
|
+
|
|
336
|
+
### useSetTrackingPreference
|
|
337
|
+
|
|
338
|
+
This hook is used to set the saved cookie preference in cache
|
|
339
|
+
|
|
340
|
+
Example Usage:
|
|
341
|
+
|
|
342
|
+
```typescript
|
|
343
|
+
import { useSetTrackingPreference, Region, TrackingCategory } from 'cb-cookie-manager';
|
|
344
|
+
|
|
345
|
+
const SomeComponent = () => {
|
|
346
|
+
const setTrackingPreference = useSetTrackingPreference();
|
|
347
|
+
|
|
348
|
+
const handleSave = useCallback(() => {
|
|
349
|
+
setTrackingPreference({
|
|
350
|
+
region: Region.Default,
|
|
351
|
+
consent: [TrackingCategory.Functional],
|
|
352
|
+
});
|
|
353
|
+
console.log('cookie_consent_manager_saved_tapped');
|
|
354
|
+
}, [setTrackingPreference]);
|
|
355
|
+
|
|
356
|
+
return (
|
|
357
|
+
<div>
|
|
358
|
+
<Button onClick={handleSave} large>
|
|
359
|
+
Save Preference
|
|
360
|
+
</Button>
|
|
361
|
+
</div>
|
|
362
|
+
)
|
|
363
|
+
}
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
### useTrackingPreference
|
|
367
|
+
|
|
368
|
+
This hook returns the cached preference and if no preference is cached, it returns the default preference based on user's region
|
|
369
|
+
|
|
370
|
+
Example Usage:
|
|
371
|
+
|
|
372
|
+
```typescript
|
|
373
|
+
import { useTrackingPreference } from 'cb-cookie-manager';
|
|
374
|
+
|
|
375
|
+
const SomeComponent = () => {
|
|
376
|
+
const initialTrackingPreference = useTrackingPreference();
|
|
377
|
+
|
|
378
|
+
return (
|
|
379
|
+
<div>
|
|
380
|
+
{initialTrackingPreference}
|
|
381
|
+
</div>
|
|
382
|
+
)
|
|
383
|
+
}
|
|
384
|
+
```
|
|
385
|
+
|
|
386
|
+
### areCookiesEnabled
|
|
387
|
+
|
|
388
|
+
This hook is used to determine if cookies have been enabled on user's browser
|
|
389
|
+
|
|
390
|
+
Example usage:
|
|
391
|
+
|
|
392
|
+
```typescript
|
|
393
|
+
|
|
394
|
+
import { areCookiesEnabled } from 'cb-cookie-manager';
|
|
395
|
+
|
|
396
|
+
|
|
397
|
+
const SomeComponent = () => {
|
|
398
|
+
const enabled = areCookiesEnabled();
|
|
399
|
+
|
|
400
|
+
return (
|
|
401
|
+
<div>
|
|
402
|
+
{enabled? <div> Cookies Enabled </div> : <div> Cookies not enabled </div>}
|
|
403
|
+
</div>
|
|
404
|
+
)
|
|
405
|
+
}
|
|
406
|
+
```
|
|
407
|
+
|
|
408
|
+
### getDefaultTrackingPreference
|
|
409
|
+
|
|
410
|
+
This hook is used to retrieve the default tracking preference for a given user based on their region
|
|
411
|
+
|
|
412
|
+
Example usage:
|
|
413
|
+
|
|
414
|
+
```typescript
|
|
415
|
+
import { getDefaultTrackingPreference } from 'cb-cookie-manager';
|
|
416
|
+
|
|
417
|
+
const SomeComponent = () => {
|
|
418
|
+
const preference = getDefaultTrackingPreference();
|
|
419
|
+
|
|
420
|
+
return (
|
|
421
|
+
<div>
|
|
422
|
+
{preference}
|
|
423
|
+
</div>
|
|
424
|
+
)
|
|
425
|
+
}
|
|
426
|
+
```
|
|
427
|
+
|
|
428
|
+
### useTrackingManager
|
|
429
|
+
|
|
430
|
+
This hook is used to return `TrackingManagerDependencies` which includes all the values/methods which were passed into Cookie Manager Provider
|
|
431
|
+
|
|
432
|
+
Example usage:
|
|
433
|
+
|
|
434
|
+
```typescript
|
|
435
|
+
import { isOptOut, useTrackingManager } from 'cb-cookie-manager';
|
|
436
|
+
|
|
437
|
+
const SomeComponent = () => {
|
|
438
|
+
const { region } = useTrackingManager();
|
|
439
|
+
const optOut = isOptOut(region);
|
|
440
|
+
|
|
441
|
+
return (
|
|
442
|
+
<div>
|
|
443
|
+
`Region for the given user is ${region}`
|
|
444
|
+
</div>
|
|
445
|
+
)
|
|
446
|
+
}
|
|
447
|
+
```
|
|
448
|
+
|
|
449
|
+
### isOptOut
|
|
450
|
+
|
|
451
|
+
Used for determining if the current region is using the `optOut` framework
|
|
452
|
+
|
|
453
|
+
It follows the following logic in order:
|
|
454
|
+
|
|
455
|
+
- If there's no geolocation rule for the specified region then use the rule for DEFAULT region
|
|
456
|
+
- Otherwise use the following rules:
|
|
457
|
+
- optIn: Users must opt in to tracking (EU)
|
|
458
|
+
- optOut: Users must opt out of tracking (non-EU)
|
|
459
|
+
|
|
460
|
+
Example usage:
|
|
461
|
+
|
|
462
|
+
```typescript
|
|
463
|
+
import { isOptOut, useTrackingManager } from 'cb-cookie-manager';
|
|
464
|
+
|
|
465
|
+
const SomeComponent = () => {
|
|
466
|
+
const { region } = useTrackingManager();
|
|
467
|
+
const optOut = isOptOut(region);
|
|
468
|
+
|
|
469
|
+
return (
|
|
470
|
+
<div>
|
|
471
|
+
{isOptOut ? <div> In default region </div> : <div> In Eu </div>}
|
|
472
|
+
</div>
|
|
473
|
+
)
|
|
474
|
+
}
|
|
475
|
+
```
|
|
476
|
+
|
|
477
|
+
## License
|
|
478
|
+
|
|
479
|
+
Licensed under the Apache License. See [LICENSE](./LICENSE) for more information.
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { CookieAttributes } from 'js-cookie';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { SetCookieFunction } from './types';
|
|
4
|
+
type Props = {
|
|
5
|
+
children: React.ReactNode;
|
|
6
|
+
};
|
|
7
|
+
export declare const CookieProvider: ({ children }: Props) => React.JSX.Element;
|
|
8
|
+
export declare const useSetCookie: () => (cookieName: string, value: any, options?: CookieAttributes) => void;
|
|
9
|
+
export declare const useCookie: (cookieName: string) => [any | undefined, SetCookieFunction];
|
|
10
|
+
export {};
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
26
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
27
|
+
};
|
|
28
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
29
|
+
exports.useCookie = exports.useSetCookie = exports.CookieProvider = void 0;
|
|
30
|
+
const js_cookie_1 = __importDefault(require("js-cookie"));
|
|
31
|
+
const react_1 = __importStar(require("react"));
|
|
32
|
+
const constants_1 = require("./constants");
|
|
33
|
+
const TrackingManagerContext_1 = require("./TrackingManagerContext");
|
|
34
|
+
const types_1 = require("./types");
|
|
35
|
+
const getAllCookies_1 = __importStar(require("./utils/getAllCookies"));
|
|
36
|
+
const getDefaultTrackingPreference_1 = __importDefault(require("./utils/getDefaultTrackingPreference"));
|
|
37
|
+
const getDomain_1 = require("./utils/getDomain");
|
|
38
|
+
const getTrackerInfo_1 = __importDefault(require("./utils/getTrackerInfo"));
|
|
39
|
+
const hasConsent_1 = __importDefault(require("./utils/hasConsent"));
|
|
40
|
+
const isMaxKBSize_1 = __importDefault(require("./utils/isMaxKBSize"));
|
|
41
|
+
const setGTMVariables_1 = __importDefault(require("./utils/setGTMVariables"));
|
|
42
|
+
const CookieContext = (0, react_1.createContext)([{}]);
|
|
43
|
+
const CookieProvider = ({ children }) => {
|
|
44
|
+
const { config, region, shadowMode, log, onPreferenceChange } = (0, TrackingManagerContext_1.useTrackingManager)();
|
|
45
|
+
const POLL_INTERVAL = 500;
|
|
46
|
+
let cookieValues = {};
|
|
47
|
+
let trackingPreference;
|
|
48
|
+
let adTrackingPreference;
|
|
49
|
+
const removeCookies = (0, react_1.useCallback)((cookies) => {
|
|
50
|
+
cookies.forEach((c) => {
|
|
51
|
+
if (!shadowMode) {
|
|
52
|
+
js_cookie_1.default.remove(c, { domain: (0, getDomain_1.getDomainWithoutSubdomain)(), path: '/' });
|
|
53
|
+
js_cookie_1.default.remove(c, { domain: (0, getDomain_1.getHostname)(), path: '/' });
|
|
54
|
+
}
|
|
55
|
+
log('Cookie does not have consent and will be removed', {
|
|
56
|
+
cookie: c,
|
|
57
|
+
});
|
|
58
|
+
});
|
|
59
|
+
}, [shadowMode, log]);
|
|
60
|
+
(0, react_1.useEffect)(() => {
|
|
61
|
+
if (typeof window !== 'undefined') {
|
|
62
|
+
const checkCookies = () => {
|
|
63
|
+
const currentCookie = (0, getAllCookies_1.default)();
|
|
64
|
+
if (!(0, getAllCookies_1.areRecordsEqual)(cookieValues, currentCookie)) {
|
|
65
|
+
cookieValues = currentCookie;
|
|
66
|
+
trackingPreference = getTrackingPreference(cookieValues, region, config);
|
|
67
|
+
adTrackingPreference = getAdTrackingPreference(cookieValues);
|
|
68
|
+
(0, setGTMVariables_1.default)(trackingPreference, adTrackingPreference);
|
|
69
|
+
const cookiesToRemove = [];
|
|
70
|
+
Object.keys(cookieValues).forEach((c) => {
|
|
71
|
+
const trackerInfo = (0, getTrackerInfo_1.default)(c, config);
|
|
72
|
+
if (constants_1.REQUIRED_COOKIE_MANAGER_COOKIES.includes(c)) {
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
if (!trackerInfo) {
|
|
76
|
+
// This cookie is not present in the config. For legal/compliance
|
|
77
|
+
// reasons, any cookies not listed in the config may not be set.
|
|
78
|
+
cookiesToRemove.push(c);
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
if (!(0, hasConsent_1.default)(c, config, trackingPreference) &&
|
|
82
|
+
trackerInfo.type === types_1.TrackerType.COOKIE) {
|
|
83
|
+
cookiesToRemove.push(c);
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
removeCookies(cookiesToRemove);
|
|
87
|
+
}
|
|
88
|
+
};
|
|
89
|
+
checkCookies();
|
|
90
|
+
// Call the function once before setting the interval
|
|
91
|
+
const intervalId = setInterval(checkCookies, POLL_INTERVAL);
|
|
92
|
+
return () => {
|
|
93
|
+
clearInterval(intervalId);
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
}, []);
|
|
97
|
+
(0, react_1.useEffect)(() => {
|
|
98
|
+
if (onPreferenceChange) {
|
|
99
|
+
onPreferenceChange(trackingPreference);
|
|
100
|
+
}
|
|
101
|
+
}, []);
|
|
102
|
+
return react_1.default.createElement(CookieContext.Provider, { value: cookieValues }, children);
|
|
103
|
+
};
|
|
104
|
+
exports.CookieProvider = CookieProvider;
|
|
105
|
+
const useSetCookie = () => {
|
|
106
|
+
const cookieChangedRef = (0, react_1.useContext)(CookieContext);
|
|
107
|
+
const { config, region, log, shadowMode, onError } = (0, TrackingManagerContext_1.useTrackingManager)();
|
|
108
|
+
const trackingPreference = getTrackingPreference(cookieChangedRef, region, config);
|
|
109
|
+
return (0, react_1.useCallback)((cookieName, value, options) => {
|
|
110
|
+
const setCookieFunc = setCookieFunction({
|
|
111
|
+
cookieName,
|
|
112
|
+
trackingPreference,
|
|
113
|
+
config,
|
|
114
|
+
log,
|
|
115
|
+
shadowMode,
|
|
116
|
+
onError,
|
|
117
|
+
});
|
|
118
|
+
setCookieFunc(value, options);
|
|
119
|
+
}, [trackingPreference, config, log, shadowMode, onError]);
|
|
120
|
+
};
|
|
121
|
+
exports.useSetCookie = useSetCookie;
|
|
122
|
+
const setCookieFunction = ({ cookieName, trackingPreference, config, shadowMode, log, onError, }) => {
|
|
123
|
+
return (value, options) => {
|
|
124
|
+
var _a;
|
|
125
|
+
if (value === undefined || value === null) {
|
|
126
|
+
js_cookie_1.default.remove(cookieName, options);
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
const cookieHasConsent = (0, hasConsent_1.default)(cookieName, config, trackingPreference);
|
|
130
|
+
if (cookieHasConsent || shadowMode) {
|
|
131
|
+
const stringValue = JSON.stringify(value);
|
|
132
|
+
const cookieSize = (_a = options === null || options === void 0 ? void 0 : options.size) !== null && _a !== void 0 ? _a : constants_1.MAX_COOKIE_SIZE;
|
|
133
|
+
/*
|
|
134
|
+
Url encoded cookie string (since that is what Cookies.set coverts the string into) including its name must not exceed 4KB
|
|
135
|
+
For example, "," becomes %22%2C%2C making it go from 3 characters to now 9. The size has tripled.
|
|
136
|
+
This is why we need to compare the url encoded stringValue instead of the stringValue itself to account for the extra characters.
|
|
137
|
+
*/
|
|
138
|
+
if ((0, isMaxKBSize_1.default)(encodeURIComponent(stringValue) + cookieName, cookieSize)) {
|
|
139
|
+
onError(new Error(`${cookieName} value exceeds ${cookieSize}KB`));
|
|
140
|
+
}
|
|
141
|
+
else {
|
|
142
|
+
const newOptions = options ? Object.assign({}, options) : undefined;
|
|
143
|
+
if (newOptions === null || newOptions === void 0 ? void 0 : newOptions.size) {
|
|
144
|
+
delete newOptions.size;
|
|
145
|
+
}
|
|
146
|
+
js_cookie_1.default.set(cookieName, stringValue, newOptions);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
if (!cookieHasConsent) {
|
|
150
|
+
log('Cookie does not have consent and will not be set', {
|
|
151
|
+
cookie: cookieName,
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
};
|
|
155
|
+
};
|
|
156
|
+
const getTrackingPreference = (cookieCache, region, config) => {
|
|
157
|
+
const trackingPreference = region === 'EU'
|
|
158
|
+
? cookieCache[constants_1.EU_CONSENT_PREFERENCES_COOKIE]
|
|
159
|
+
: cookieCache[constants_1.DEFAULT_CONSENT_PREFERENCES_COOKIE];
|
|
160
|
+
return trackingPreference || (0, getDefaultTrackingPreference_1.default)(region, config);
|
|
161
|
+
};
|
|
162
|
+
const adTrackingDefault = { value: 'true' };
|
|
163
|
+
const getAdTrackingPreference = (cookieCache) => {
|
|
164
|
+
const adTrackingPreference = cookieCache[constants_1.ADVERTISING_SHARING_ALLOWED];
|
|
165
|
+
return adTrackingPreference || adTrackingDefault;
|
|
166
|
+
};
|
|
167
|
+
const useCookie = (cookieName) => {
|
|
168
|
+
const cookieCache = (0, react_1.useContext)(CookieContext);
|
|
169
|
+
const { config, region, log, shadowMode, onError } = (0, TrackingManagerContext_1.useTrackingManager)();
|
|
170
|
+
const trackingPreference = getTrackingPreference(cookieCache, region, config);
|
|
171
|
+
const setCookie = setCookieFunction({
|
|
172
|
+
cookieName,
|
|
173
|
+
trackingPreference,
|
|
174
|
+
config,
|
|
175
|
+
log,
|
|
176
|
+
shadowMode,
|
|
177
|
+
onError,
|
|
178
|
+
});
|
|
179
|
+
const cookieValue = (0, react_1.useContext)(CookieContext)[cookieName];
|
|
180
|
+
return [cookieValue, setCookie];
|
|
181
|
+
};
|
|
182
|
+
exports.useCookie = useCookie;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { TrackingManagerDependencies } from './types';
|
|
3
|
+
export declare const useTrackingManager: () => TrackingManagerDependencies;
|
|
4
|
+
export declare function Provider({ children, ...restProps }: {
|
|
5
|
+
children: React.ReactNode;
|
|
6
|
+
} & TrackingManagerDependencies): React.JSX.Element;
|