From 2191eb34b501c21f963f0e39426f89b5e6baed39 Mon Sep 17 00:00:00 2001
From: Seth Silesky <5115498+silesky@users.noreply.github.com>
Date: Mon, 28 Aug 2023 16:17:53 -0500
Subject: [PATCH] Consent: add bundled version that can be loaded via script
tag (#938)
---
.changeset/angry-cows-compete.md | 7 +
.changeset/heavy-boxes-grab.md | 5 +
examples/standalone-playground/package.json | 6 +-
.../pages/index-consent.html | 165 ++
packages/config-webpack/README.md | 3 +
packages/config-webpack/package.json | 19 +
.../config-webpack/webpack.config.common.js | 71 +
.../src/page-bundles/onetrust/index.ts | 8 +-
.../src/page-bundles/snippet/index.ts | 4 +-
.../domain/__tests__/create-wrapper.test.ts | 6 +
.../src/domain/__tests__/typedef-tests.ts | 3 +
.../src/domain/create-wrapper.ts | 1 +
.../consent-tools/src/types/wrapper.ts | 4 +-
.../consent-wrapper-onetrust/README.md | 114 +-
.../img/onetrust-popup.jpg | Bin 0 -> 238267 bytes
.../consent-wrapper-onetrust/package.json | 20 +-
.../src/domain/__tests__/wrapper.test.ts | 8 +-
.../src/domain/wrapper.ts | 8 +-
.../consent-wrapper-onetrust/src/index.ts | 2 +-
.../consent-wrapper-onetrust/src/index.umd.ts | 11 +
.../webpack.config.js | 25 +
yarn.lock | 2215 ++++++++++++++++-
22 files changed, 2567 insertions(+), 138 deletions(-)
create mode 100644 .changeset/angry-cows-compete.md
create mode 100644 .changeset/heavy-boxes-grab.md
create mode 100644 examples/standalone-playground/pages/index-consent.html
create mode 100644 packages/config-webpack/README.md
create mode 100644 packages/config-webpack/package.json
create mode 100644 packages/config-webpack/webpack.config.common.js
create mode 100644 packages/consent/consent-wrapper-onetrust/img/onetrust-popup.jpg
create mode 100644 packages/consent/consent-wrapper-onetrust/src/index.umd.ts
create mode 100644 packages/consent/consent-wrapper-onetrust/webpack.config.js
diff --git a/.changeset/angry-cows-compete.md b/.changeset/angry-cows-compete.md
new file mode 100644
index 000000000..f9288f9dd
--- /dev/null
+++ b/.changeset/angry-cows-compete.md
@@ -0,0 +1,7 @@
+---
+'@segment/analytics-consent-wrapper-onetrust': minor
+---
+
+- Change API from oneTrust(analytics) -> withOneTrust(analytics). Allow withOneTrust(analytics).load(...).
+- Add a umd bundle for snippet users
+
diff --git a/.changeset/heavy-boxes-grab.md b/.changeset/heavy-boxes-grab.md
new file mode 100644
index 000000000..cf4cb6f2b
--- /dev/null
+++ b/.changeset/heavy-boxes-grab.md
@@ -0,0 +1,5 @@
+---
+'@segment/analytics-consent-tools': patch
+---
+
+Have `createWrapper` return analytics instance to allow `.load` to be chained.
diff --git a/examples/standalone-playground/package.json b/examples/standalone-playground/package.json
index fd6983054..cbe32e8b1 100644
--- a/examples/standalone-playground/package.json
+++ b/examples/standalone-playground/package.json
@@ -5,11 +5,13 @@
"hoistingLimits": "workspaces"
},
"scripts": {
- ".": "yarn run -T turbo run --filter=@example/standalone-playground",
- "dev": "yarn concurrently 'yarn run -T watch --filter=standalone-playground' 'sleep 10 && yarn http-server .'",
+ ".": "yarn run -T turbo run --filter=@example/standalone-playground...",
+ "start": "yarn http-server . -o /pages",
+ "dev": "yarn concurrently 'yarn . build && yarn start' 'sleep 10 && yarn . watch'",
"concurrently": "yarn run -T concurrently"
},
"dependencies": {
+ "@segment/analytics-consent-wrapper-onetrust": "workspace:^",
"@segment/analytics-next": "workspace:^"
},
"devDependencies": {
diff --git a/examples/standalone-playground/pages/index-consent.html b/examples/standalone-playground/pages/index-consent.html
new file mode 100644
index 000000000..2c908fc0e
--- /dev/null
+++ b/examples/standalone-playground/pages/index-consent.html
@@ -0,0 +1,165 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/packages/config-webpack/README.md b/packages/config-webpack/README.md
new file mode 100644
index 000000000..339cfa3bf
--- /dev/null
+++ b/packages/config-webpack/README.md
@@ -0,0 +1,3 @@
+# @internal/config-webpack
+
+This package is for sharing basic webpack configuration / browser support between all of the analytics.js artifacts in this monorepo.
diff --git a/packages/config-webpack/package.json b/packages/config-webpack/package.json
new file mode 100644
index 000000000..c243c7314
--- /dev/null
+++ b/packages/config-webpack/package.json
@@ -0,0 +1,19 @@
+{
+ "name": "@internal/config-webpack",
+ "version": "0.0.0",
+ "private": true,
+ "packageManager": "yarn@3.4.1",
+ "devDependencies": {
+ "@babel/cli": "^7.22.10",
+ "@babel/core": "^7.22.11",
+ "@babel/preset-env": "^7.22.10",
+ "@babel/preset-typescript": "^7.22.11",
+ "@types/circular-dependency-plugin": "^5",
+ "babel-loader": "^8.0.0",
+ "circular-dependency-plugin": "^5.2.2",
+ "terser-webpack-plugin": "^5.1.4",
+ "webpack": "^5.76.0",
+ "webpack-cli": "^4.8.0",
+ "webpack-merge": "^5.9.0"
+ }
+}
diff --git a/packages/config-webpack/webpack.config.common.js b/packages/config-webpack/webpack.config.common.js
new file mode 100644
index 000000000..4710464c2
--- /dev/null
+++ b/packages/config-webpack/webpack.config.common.js
@@ -0,0 +1,71 @@
+const TerserPlugin = require('terser-webpack-plugin')
+const CircularDependencyPlugin = require('circular-dependency-plugin')
+
+const isProd = process.env.NODE_ENV === 'production'
+const isWatch = process.env.WATCH === 'true'
+
+/**
+ * This is a base webpack config that is used for all generic web packages.
+ * It should contain the same support as analytics.js (e.g. es5, minified, etc)
+ *
+ *
+ * @type { import('webpack').Configuration }
+ */
+module.exports = {
+ devtool: 'source-map',
+ stats: isWatch ? 'errors-warnings' : 'normal',
+ mode: isProd ? 'production' : 'development',
+ module: {
+ rules: [
+ {
+ test: /\.(ts|js)$/,
+ use: [
+ {
+ loader: 'babel-loader',
+ options: {
+ presets: [
+ ['@babel/preset-typescript'],
+ [
+ '@babel/preset-env',
+ {
+ targets: {
+ ie: 11,
+ },
+ },
+ ],
+ ],
+ },
+ },
+ ],
+ exclude: /node_modules/,
+ },
+ ],
+ },
+ optimization: {
+ moduleIds: 'deterministic',
+ minimize: isProd,
+ minimizer: [
+ new TerserPlugin({
+ extractComments: false,
+ terserOptions: {
+ // not sure why, if we target es5, we can set ecma to 2015 here without breaking ie11.
+ // this from the original webpack config had that netto set up, so leaving it as is.
+ ecma: '2015',
+ mangle: true,
+ compress: true,
+ output: {
+ comments: false,
+ },
+ },
+ }),
+ ],
+ },
+ resolve: {
+ extensions: ['.ts', '.js'],
+ },
+ plugins: [
+ new CircularDependencyPlugin({
+ failOnError: true,
+ }),
+ ],
+}
diff --git a/packages/consent/consent-tools-integration-tests/src/page-bundles/onetrust/index.ts b/packages/consent/consent-tools-integration-tests/src/page-bundles/onetrust/index.ts
index 62da28671..04c7f2ce2 100644
--- a/packages/consent/consent-tools-integration-tests/src/page-bundles/onetrust/index.ts
+++ b/packages/consent/consent-tools-integration-tests/src/page-bundles/onetrust/index.ts
@@ -1,16 +1,14 @@
import { AnalyticsBrowser } from '@segment/analytics-next'
-import { oneTrust } from '@segment/analytics-consent-wrapper-onetrust'
+import { withOneTrust } from '@segment/analytics-consent-wrapper-onetrust'
export const analytics = new AnalyticsBrowser()
-oneTrust(analytics, {
+withOneTrust(analytics, {
disableConsentChangedEvent: false,
integrationCategoryMappings: {
Fullstory: ['C0001'],
'Actions Amplitude': ['C0004'],
},
-})
+}).load({ writeKey: '9lSrez3BlfLAJ7NOChrqWtILiATiycoc' })
;(window as any).analytics = analytics
-
-analytics.load({ writeKey: '9lSrez3BlfLAJ7NOChrqWtILiATiycoc' })
void window.analytics.page().then(console.log)
diff --git a/packages/consent/consent-tools-integration-tests/src/page-bundles/snippet/index.ts b/packages/consent/consent-tools-integration-tests/src/page-bundles/snippet/index.ts
index da6c6948e..89b0648f7 100644
--- a/packages/consent/consent-tools-integration-tests/src/page-bundles/snippet/index.ts
+++ b/packages/consent/consent-tools-integration-tests/src/page-bundles/snippet/index.ts
@@ -1,7 +1,7 @@
/* eslint-disable @typescript-eslint/no-floating-promises */
-import { oneTrust } from '@segment/analytics-consent-wrapper-onetrust'
+import { withOneTrust } from '@segment/analytics-consent-wrapper-onetrust'
-oneTrust(window.analytics, {
+withOneTrust(window.analytics, {
integrationCategoryMappings: {
Fullstory: ['C0001'],
'Actions Amplitude': ['C0004'],
diff --git a/packages/consent/consent-tools/src/domain/__tests__/create-wrapper.test.ts b/packages/consent/consent-tools/src/domain/__tests__/create-wrapper.test.ts
index d3ec7ee2c..4ba852d98 100644
--- a/packages/consent/consent-tools/src/domain/__tests__/create-wrapper.test.ts
+++ b/packages/consent/consent-tools/src/domain/__tests__/create-wrapper.test.ts
@@ -117,6 +117,12 @@ describe(createWrapper, () => {
expect(addSourceMiddlewareSpy).toBeCalledWith(expect.any(Function))
})
+ it('should be chainable', async () => {
+ await wrapTestAnalytics().load(DEFAULT_LOAD_SETTINGS)
+ const { args } = getAnalyticsLoadLastCall()
+ expect(args.length).toBeTruthy()
+ })
+
describe('shouldLoad', () => {
describe('Throwing errors / aborting load', () => {
const createShouldLoadThatThrows = (
diff --git a/packages/consent/consent-tools/src/domain/__tests__/typedef-tests.ts b/packages/consent/consent-tools/src/domain/__tests__/typedef-tests.ts
index 06b69090a..ba2b47dc3 100644
--- a/packages/consent/consent-tools/src/domain/__tests__/typedef-tests.ts
+++ b/packages/consent/consent-tools/src/domain/__tests__/typedef-tests.ts
@@ -15,4 +15,7 @@ type Extends = T extends U ? true : false
const f: Extends = true
const g: Extends = true
console.log(f, g)
+
+ // should be chainable
+ wrap({} as AnalyticsBrowser).load({ writeKey: 'foo' })
}
diff --git a/packages/consent/consent-tools/src/domain/create-wrapper.ts b/packages/consent/consent-tools/src/domain/create-wrapper.ts
index 7ef94e588..caa619a67 100644
--- a/packages/consent/consent-tools/src/domain/create-wrapper.ts
+++ b/packages/consent/consent-tools/src/domain/create-wrapper.ts
@@ -160,6 +160,7 @@ export const createWrapper: CreateWrapper = (createWrapperOptions) => {
})
}
analytics.load = loadWithConsent
+ return analytics
}
}
diff --git a/packages/consent/consent-tools/src/types/wrapper.ts b/packages/consent/consent-tools/src/types/wrapper.ts
index 5d8267a4f..f1186caa5 100644
--- a/packages/consent/consent-tools/src/types/wrapper.ts
+++ b/packages/consent/consent-tools/src/types/wrapper.ts
@@ -41,7 +41,9 @@ export interface AnyAnalytics {
**/
// Why type this as 'object' rather than 'AnyAnalytics'? IMO, the chance of a false positive is much higher than the chance that someone will pass in an object that is not an analytics instance.
// We have an assertion function that throws an error if the analytics instance is not compatible.
-export type Wrapper = (analyticsInstance: object) => void
+export type Wrapper = (
+ analyticsInstance: Analytics
+) => Analytics
/**
* Create a function which wraps analytics instances to add consent management.
diff --git a/packages/consent/consent-wrapper-onetrust/README.md b/packages/consent/consent-wrapper-onetrust/README.md
index bac815f3c..b577bd97e 100644
--- a/packages/consent/consent-wrapper-onetrust/README.md
+++ b/packages/consent/consent-wrapper-onetrust/README.md
@@ -1,64 +1,124 @@
-This package is for the OneTrust integration for analytics consent
+# @segment/analytics-consent-wrapper-onetrust
+### Try our Playground! [Next.js CodeSandbox](https://codesandbox.io/p/sandbox/focused-bhaskara-jysqr5) 🚀
+
+
# Quick Start
## Configure OneTrust + Segment
+
### Ensure that the OneTrust Banner SDK is loaded first
+
```html
-
-
+
+
+
```
### Ensure that consent is enabled and that you have created your Integration -> Consent Category Mappings
+
- Ensure that your integrations in the Segment UI have consent enabled, and that they map to your Consent Category IDs (also called Cookie Group IDs or Cookie Consent IDs).
-The IDs look like "CAT0001", "CAT0002"and are configurable in OneTrust
-![onetrust category ids](img/onetrust-cat-id.jpg)
+ The IDs look like "C0001", "C0002"and are configurable in OneTrust
+ ![onetrust category ids](img/onetrust-cat-id.jpg)
-- Debugging: this library expects the [OneTrust Banner SDK](https://community.cookiepro.com/s/article/UUID-d8291f61-aa31-813a-ef16-3f6dec73d643?language=en_US) to be available in order interact with OneTrust. This library derives the group IDs that are active for the current user from the `window.OneTrustActiveGroups` object provided by the OneTrust SDK. [Read this for more information [community.cookiepro.com]](https://community.cookiepro.com/s/article/UUID-66bcaaf1-c7ca-5f32-6760-c75a1337c226?language=en_US).
+- Debugging: this library expects the [OneTrust Banner SDK](https://community.cookiepro.com/s/article/UUID-d8291f61-aa31-813a-ef16-3f6dec73d643?language=en_US) to be available in order interact with OneTrust. This library derives the group IDs that are active for the current user from the `window.OneTrustActiveGroups` object provided by the OneTrust SDK. [Read this for more information [community.cookiepro.com]](https://community.cookiepro.com/s/article/UUID-66bcaaf1-c7ca-5f32-6760-c75a1337c226?language=en_US).
-## Install dependency
+## For `npm` library users
+
+1. Install the package
```sh
+# npm
npm install @segment/analytics-consent-wrapper-onetrust
-# or
-
+# yarn
yarn add @segment/analytics-consent-wrapper-onetrust
-```
-## For `npm` library users
+# pnpm
+pnpm add @segment/analytics-consent-wrapper-onetrust
+```
-- Use the following initialization code
+2. Initialize alongside analytics
```ts
-import { oneTrust } from '@segment/analytics-consent-wrapper-onetrust'
+import { withOneTrust } from '@segment/analytics-consent-wrapper-onetrust'
import { AnalyticsBrowser } from '@segment/analytics-next'
export const analytics = new AnalyticsBrowser()
-oneTrust(analytics)
-analytics.load({ writeKey: ' })
+withOneTrust(analytics).load({ writeKey: ' })
```
-## For snippet users (window.analytics) who _also_ use a bundler like webpack
-### _NOTE:_ a pre-bundled version that can be loaded through a `
+
+
+
+
+
+
+
```
-- Use the following initialization code
+#### ⚠️ Reminder: _delete_ `analytics.load('....')` from the original Segment snippet so that only .load() is only called after `withOneTrust` is called. See comment in example above.
-```ts
-import { oneTrust } from '@segment/analytics-consent-wrapper-onetrust'
+## Other examples:
+
+> Note: Playgrounds are meant for experimentation / testing, and as such, may be a bit overly complicated.
+> We recommend you try to follcaow the documentation for best practice.
-oneTrust(window.analytics)
-window.analytics.load('')
+- [Standalone playground](/examples/standalone-playground/pages/index-consent.html)
+
+## Environments
+
+### Build Artifacts
+
+- We build three versions of the library:
+
+1. `cjs` (CommonJS modules) - for library users
+2. `esm` (es6 modules) - for library users
+3. `umd` (bundle) - for snippet users (typically)
+
+### Browser Support
+
+- `cjs/esm` - ONLY support modern JS syntax. We expect our typical `npm install` users to employ something like babel if they need legacy browser support.
+
+- `umd` - Support back to IE11, but **do not** polyfill . See our docs on [supported browsers](https://segment.com/docs/connections/sources/catalog/libraries/website/javascript/supported-browsers).
+
+In order to get full ie11 support, you are expected to bring your own polyfills. e.g. adding the following to your script tag:
+
+```html
+
+```
+
+or
+
+```html
+
```
diff --git a/packages/consent/consent-wrapper-onetrust/img/onetrust-popup.jpg b/packages/consent/consent-wrapper-onetrust/img/onetrust-popup.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..358972a4f00b5f39c5202075ed81608be56a918f
GIT binary patch
literal 238267
zcmeFZ2Ut_xwkR5;H|ZipLN6j!iqaw?T|_`dK!}L+E+9cdf+8Tj2`DH*sZymYAfY2D
zARr(hLV`*SB$Ni{fG6O!KLkuX$80PH(0$EvsPJ%!n77zm+6Nnx-qXQiQzIgw34m?07|L@o1
zy+I6r)B%AEfL{=ZzL4(UYZe~)`(1{TLi)d-GqU`yc!*(*^$HCQ(os0@8!Pf?VBv-9yE1xqEsC=u2+3p(Vw=Z|h6iYg(yV1sS<}d7It4
z<8F8F(iOLRzHVo4OF|69^-U8z|(hbd+69+F!|fFz<>IZf9qs;c(`)-Y30B>o+@f*&z@CL
zRaa40R|0A%g+v5|y26wKLZtrwh70Z?Zg;$cLcIe6#DBlh^;Te5sJqi
z28G@6`{SLr-BjHD-2L4HLPG%X)l`1J>b9FsNZ2hOcel{L_3XT>rwVYY@}F*~{BGet
zwD`Ni?@Is}zfb>x4+HVP%3m1x3j=>);4cjPg@L~?@c%yy{JTWu9sr0@;efmZI_w1T
zurRVPl+e>jf{yUe(euz9_JY8Gl*dT-NBJ$Q{VsGz=ouK9m|0la*ntX7+@K?L^z=s<
z=ouLq011#T3b+qq;9=yIP%~uWvvFmX4CYtApYei4>U>?7fbAGw`t+?k4_Mib2_6>`
zmXVc{S2(Gmsil49td7wIV-r&|a|^pGSFhP$cW`vO?e5{}~MnudJ>Sws&^-i2I~p2fyJ0gwuZm3;6!0aPa_e9bsUgXJGyf7u}KY-+=QlFiNN~
z@fzANy9V<~s^4efKcDfUu8URbv@KrX)}1l7W6~NJ8NzSS{($UX1MI>7Ey(@>*uTRy
z2QmUA`QPOT@JD~-2ryLiKw)5F_+6Nonf@rue=9716xQE`{U7BJcnRI_C+X=Kfj@Q@
zCYFEP`Vulzw>J(hGw;jbJr|en
zcQBH8docUar*73Z)F()Jq#S7h7aGY;sujG)<2
z{55C{f{6gxKv%)9cGM+=EpUGDlxf0>J6sI;YD(Wf{P_j%X4j_To?{37A?QIN2d&58
zjM#xEEqCrR^EOM5{{@6i1EDfY`P<3Ly9b{bG;9k>GovAgp9G(=O*UNSbRXC^U2;0+
zRyGw4d50O#c}iW_nMIvrcl3>CiRQHw
z3%otP>xS1l?aD-R4OjjN-QLF39X1KW4SCDaceZqBfs#GCi$#BhoxbVKSq1t@Uo5
zUrXNAUVGKSp+P=o6S2aWw5g_64!cWa{^GpWV=*@<9n$#k_F%Uh+PwS7!l|Jb4Z9;D
zj^W`sQ+I2_!X*cIIs2YAM>E6olw+O--uZN6+f?I#0HZ