Skip to content

Commit

Permalink
update consent changed event handling
Browse files Browse the repository at this point in the history
  • Loading branch information
narciero committed Mar 26, 2024
1 parent d4c4839 commit 5784629
Show file tree
Hide file tree
Showing 5 changed files with 34 additions and 60 deletions.
24 changes: 5 additions & 19 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ _Hightouch works to ensure Consent Manager works with most of our product pipeli

### How it works

1. The consent manager delays loading the events SDK until user consent is given, and will not load the SDK at all if the user opts out of everything. The user's tracking preferences are saved to a cookie and sent as an `identify` trait and a `Consent Updated` track event (if they haven't opted out of everything), ensuring consent data is propagated to your destinations.
1. The consent manager delays loading the events SDK until user consent is given, and will not load the SDK at all if the user opts out of everything. The user's tracking preferences are saved to a cookie and sent as a `Consent Updated` track event (if they haven't opted out of everything), ensuring consent data is propagated to your destinations.

2. **All** events will include the latest consent metadata inside the `context.consent` object:

Expand All @@ -43,29 +43,15 @@ _Hightouch works to ensure Consent Manager works with most of our product pipeli
}
```

3. Whenever a user updates their consent preferences, the following events will be emitted
- `identify` with updated preferences in `traits`
```json
{
"type": "identify",
"traits": {
"destinationTrackingPreferences": {},
"categoryTrackingPreferences": {
"marketingAndAnalytics": true,
"advertising": true,
"functional": true
}
}
}
```
3. Whenever a user updates their consent preferences, the following event will be emitted
- `track` named `Consent Updated` with updated preferences
```json
{
"type": "track",
"event": "Consent Updated",
"properties": {
"destinationTrackingPreferences": {},
"categoryTrackingPreferences": {
"destinationPreferences": {},
"categoryPreferences": {
"marketingAndAnalytics": true,
"advertising": true,
"functional": true
Expand Down Expand Up @@ -784,7 +770,7 @@ Resets the [preferences][] state to the value saved in the cookie. Useful for re

**Type**: `function(object|boolean)`

Saves the preferences currently in state to a cookie called `ht-cm-preferences`, triggers an `identify` event with `destinationTrackingPreferences` and `categoryTrackingPreferences` traits, triggers a `track` event called `Consent Updated`, and then reloads the Browser SDK using the new preferences. It can also be passed preferences like [setPreferences][] to do a final update before saving.
Saves the preferences currently in state to a cookie called `ht-cm-preferences`, triggers a `track` event named `Consent Updated`, and then reloads the Browser SDK using the new preferences. It can also be passed preferences like [setPreferences][] to do a final update before saving.

##### onError

Expand Down
7 changes: 5 additions & 2 deletions src/__tests__/consent-manager-builder/index.todo.js
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,11 @@ describe('ConsentManagerBuilder', () => {
test.skip('if defaultDestinationBehavior is set to imply and category is set to true, loads new destination', done => {
document.cookie =
'ht-cm-preferences={%22version%22:1%2C%22destinations%22:{%22Amplitude%22:true}%2C%22custom%22:{%22advertising%22:false%2C%22marketingAndAnalytics%22:true%2C%22functional%22:true}}'
window.htevents = { load() {}, identify() {}, track() {}, addSourceMiddleware() {} }
window.htevents = {
load() {},
track() {},
addSourceMiddleware() {}
}

nock('https://cdn.hightouch-events.com')
.get('/v1/projects/123/integrations')
Expand Down Expand Up @@ -248,7 +252,6 @@ describe('ConsentManagerBuilder', () => {
'ht-cm-preferences={%22version%22:1%2C%22destinations%22:{%22Amplitude%22:true}%2C%22custom%22:{%22advertising%22:false%2C%22marketingAndAnalytics%22:false%2C%22functional%22:true}}'
window.htevents = {
load() {},
identify() {},
track() {},
addSourceMiddleware() {}
}
Expand Down
36 changes: 9 additions & 27 deletions src/__tests__/consent-manager-builder/preferences.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ describe('preferences', () => {
})

test('savePreferences() saves the preferences', () => {
const htevents = { identify: sinon.spy(), track: sinon.spy() }
const htevents = { track: sinon.spy() }
;(window as any).htevents = htevents

Check warning on line 57 in src/__tests__/consent-manager-builder/preferences.test.ts

View workflow job for this annotation

GitHub Actions / build (16.x)

Unexpected any. Specify a different type
document.cookie = ''

Expand All @@ -70,17 +70,11 @@ describe('preferences', () => {
cookieDomain: undefined
})

expect(htevents.identify.calledOnce).toBe(true)
expect(htevents.identify.args[0][0]).toMatchObject({
destinationTrackingPreferences: destinationPreferences,
categoryTrackingPreferences: customPreferences
})

expect(htevents.track.calledOnce).toBe(true)
expect(htevents.track.args[0][0]).toBe('Consent Updated')
expect(htevents.track.args[0][1]).toMatchObject({
destinationTrackingPreferences: destinationPreferences,
categoryTrackingPreferences: customPreferences
destinationPreferences: destinationPreferences,
categoryPreferences: customPreferences
})

expect(
Expand All @@ -91,7 +85,7 @@ describe('preferences', () => {
})

test('savePreferences() sets the cookie domain', () => {
const htevents = { identify: sinon.spy(), track: sinon.spy() }
const htevents = { track: sinon.spy() }
;(window as any).htevents = htevents

Check warning on line 89 in src/__tests__/consent-manager-builder/preferences.test.ts

View workflow job for this annotation

GitHub Actions / build (16.x)

Unexpected any. Specify a different type
document.cookie = ''

Expand All @@ -105,25 +99,19 @@ describe('preferences', () => {
cookieDomain: 'example.com'
})

expect(htevents.identify.calledOnce).toBe(true)
expect(htevents.identify.args[0][0]).toMatchObject({
destinationTrackingPreferences: destinationPreferences,
categoryTrackingPreferences: undefined
})

expect(htevents.track.calledOnce).toBe(true)
expect(htevents.track.args[0][0]).toBe('Consent Updated')
expect(htevents.track.args[0][1]).toMatchObject({
destinationTrackingPreferences: destinationPreferences,
categoryTrackingPreferences: undefined
destinationPreferences: destinationPreferences,
categoryPreferences: undefined
})

// TODO: actually check domain
// expect(document.cookie.includes('domain=example.com')).toBe(true)
})

test('savePreferences() sets the cookie with custom key', () => {
const htevents = { identify: sinon.spy(), track: sinon.spy() }
const htevents = { track: sinon.spy() }
;(window as any).htevents = htevents

Check warning on line 115 in src/__tests__/consent-manager-builder/preferences.test.ts

View workflow job for this annotation

GitHub Actions / build (16.x)

Unexpected any. Specify a different type
document.cookie = ''

Expand All @@ -138,17 +126,11 @@ describe('preferences', () => {
cookieName: 'custom-tracking-preferences'
})

expect(htevents.identify.calledOnce).toBe(true)
expect(htevents.identify.args[0][0]).toMatchObject({
destinationTrackingPreferences: destinationPreferences,
categoryTrackingPreferences: undefined
})

expect(htevents.track.calledOnce).toBe(true)
expect(htevents.track.args[0][0]).toBe('Consent Updated')
expect(htevents.track.args[0][1]).toMatchObject({
destinationTrackingPreferences: destinationPreferences,
categoryTrackingPreferences: undefined
destinationPreferences: destinationPreferences,
categoryPreferences: undefined
})

expect(document.cookie.includes('custom-tracking-preferences')).toBe(true)
Expand Down
26 changes: 15 additions & 11 deletions src/consent-manager-builder/preferences.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,17 +64,21 @@ export function savePreferences({
}: SavePreferences) {
const wd = window as WindowWithHtEvents
if (wd.htevents) {
wd.htevents.identify({
destinationTrackingPreferences: destinationPreferences,
// use `categoryTrackingPreferences` here for consistency with `context.consent.categoryPreferences`
categoryTrackingPreferences: customPreferences
})

wd.htevents.track('Consent Updated', {
destinationTrackingPreferences: destinationPreferences,
// use `categoryTrackingPreferences` here for consistency with `context.consent.categoryPreferences`
categoryTrackingPreferences: customPreferences
})
wd.htevents.track(
'Consent Updated',
{
destinationPreferences,
// use `categoryPreferences` here for consistency with `context.consent.categoryPreferences`
categoryPreferences: customPreferences
},
{
// update `context.consent` here to immediately reflect the updated preferences
consent: {
destinationPreferences,
categoryPreferences: customPreferences
}
}
)
} else {
console.warn('window.htevents not found...is the SDK snippet included on the page?')
}
Expand Down
1 change: 0 additions & 1 deletion src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ export type HtEventsBrowserOptions = {
export type HtEventsBrowser = {
initialized: boolean
load: (writeKey: string, options?: HtEventsBrowserOptions) => void
identify: (properties: Record<string, any>) => void
track: (event: string, properties: Record<string, any>, options?: any, callback?: any) => void
addSourceMiddleware: (middleware: Middleware) => void
}
Expand Down

0 comments on commit 5784629

Please sign in to comment.