Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds Rakuten Affiliate Link Consent URL Param #11

Open
wants to merge 5 commits into
base: trunk
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 1.5.0 (August 9th, 2020)

- Adds support for Rakuten affiliate links consent parameter

## 1.4.0 (July 14th, 2020)

- Updates Chorus to default to default "yes" to the request of "Has been notified of rights" clause of the CCPA
Expand Down
92 changes: 89 additions & 3 deletions dist/data-privacy-compliance.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion dist/data-privacy-compliance.js.map

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "data-privacy-compliance",
"version": "1.4.0",
"version": "1.5.0",
"description": "Vox Media's library for implementing data privacy frameworks",
"main": "dist/data-privacy-compliance.js",
"license": "Apache-2.0",
Expand Down
3 changes: 2 additions & 1 deletion src/frameworks/index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
const CcpaOnChorus = require('./ccpa_on_chorus');
const CcpaFromUsPrivacyString = require('./ccpa_from_us_privacy_string');
const UsPrivacyStringAndAPIGenerator = require('./us_privacy_string_and_api_generator');
const RakutenConstentGenerator = require('./rakuten_consent_generator');

module.exports = [CcpaOnChorus, CcpaFromUsPrivacyString, UsPrivacyStringAndAPIGenerator];
module.exports = [CcpaOnChorus, CcpaFromUsPrivacyString, UsPrivacyStringAndAPIGenerator, RakutenConstentGenerator];
53 changes: 53 additions & 0 deletions src/frameworks/rakuten_consent_generator.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
const FrameworkBase = require('./base');
const RAKUTEN_CONSENT_PARAM = 'cnst';

class RakutenConsentGenerator extends FrameworkBase {
constructor() {
super();
this.document = document;
this.rakutenLinkSelector = 'a[href^="https://click.linksynergy.com"]';
}

name() {
return 'RakutenConsentGenerator';
}

isApplicable() {
// This generator depends on being able to generate a usPrivacyString
// this is checked when this Generator is being called, so load order isn't important
// since all the generators are loaded by the time they are being run
return this.document && this.privacyComplianceInstance.canGenerate('usPrivacyString');
}

supportedGenerators() {
return ['addConsentParameterToCommerceLinks'];
}

useConfig({ document, rakutenLinkSelector }) {
if (document) {
this.document = document;
}
if (rakutenLinkSelector) {
this.rakutenLinkSelector = rakutenLinkSelector;
}
}

addConsentParameterToCommerceLinks(callback = () => {}) {
let usp;
this.privacyComplianceInstance.Generator.usPrivacyString(val => (usp = val));

const allRakutenLinks = Array.from(this.document.querySelectorAll(this.rakutenLinkSelector));
const rakutenLinksThatNeedConsentParams = allRakutenLinks.filter(
link => !link.href?.includes(RAKUTEN_CONSENT_PARAM + '=')
);
rakutenLinksThatNeedConsentParams.forEach(link => {
this.log('Adding rakuten consent parameter to a link', link.href, usp);

link.href += link.href.includes('?') ? '&' : '?' + `${RAKUTEN_CONSENT_PARAM}=c${usp}`;
});

callback(rakutenLinksThatNeedConsentParams, this);
}
}

module.exports = RakutenConsentGenerator;
8 changes: 6 additions & 2 deletions src/frameworks/us_privacy_string_and_api_generator.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,12 @@ class UsPrivacyStringAndAPIGenerator extends FrameworkBase {
}

useConfig({ window, document }) {
this.window = window;
this.document = document;
if (window) {
this.window = window;
}
if (document) {
this.document = document;
}
}

usPrivacyString(callback = () => {}) {
Expand Down
1 change: 1 addition & 0 deletions src/privacy_compliance.js
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ class PrivacyCompliance {

// For use with testing only
reset() {
this.log(`Reset called. Removing ${this.frameworks.length} framework(s)`);
this.frameworks = [];
this.supportedCapabilities = new Set();
this.supportedGenerators = new Set();
Expand Down
65 changes: 65 additions & 0 deletions test/rakuten_consent_generator.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
const PrivacyCompliance = require('../src/privacy_compliance');
const RakutenConsentGenerator = require('../src/frameworks/rakuten_consent_generator');
const FrameworkBase = require('../src/frameworks/base');

class MockUSPrivacyStringGenerator extends FrameworkBase {
constructor() {
super();
this.usp = '1YYY';
}

config({ usp }) {
this.usp = usp;
}

name() {
return 'MockUSPrivacyStringGenerator';
}

supportedGenerators() {
return ['usPrivacyString'];
}

usPrivacyString(cb) {
cb(this.usp);
}
}

describe('Rakuten Consent Generator', () => {
beforeEach(() => {
PrivacyCompliance.reset();
PrivacyCompliance.addFramework(new RakutenConsentGenerator());
PrivacyCompliance.addFramework(new MockUSPrivacyStringGenerator());
});

it('should find rakuten links', () => {
document.body.innerHTML = `
<div>
<a href="https://click.linksynergy.com/buy/this/now.php">A thing worth buying!</a>
</div>
`;

let foundLinks;
PrivacyCompliance.Generator.addConsentParameterToCommerceLinks(rakutenLinks => (foundLinks = rakutenLinks));
expect(foundLinks && foundLinks.length).toBe(1);

// the callback list of links should include the correct string
expect(foundLinks.every(a => a.href.includes('1YYY'))).toBe(true);

// lets check the document is updated too
expect(document.querySelector('a').href).toBe('https://click.linksynergy.com/buy/this/now.php?cnst=c1YYY');
});

it('should ignore all the other links', () => {
document.body.innerHTML = `
<div>
<a href="https://click.linksynergy.com/buy/this/now.php">A thing worth buying!</a>
<a href="https://someothercompany.iowa.us/beard/oil/buy.php">Does any one need beard oil?</a>
</div>
`;

PrivacyCompliance.Generator.addConsentParameterToCommerceLinks();
expect(document.querySelector('a').href).toBe('https://click.linksynergy.com/buy/this/now.php?cnst=c1YYY');
expect(document.querySelectorAll('a')[1].href.includes('c1YYY')).toBeFalsy();
});
});