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

Connect id : storage duration updates and no longer require puid or he to be set #9965

Merged
merged 10 commits into from
Jun 1, 2023
92 changes: 80 additions & 12 deletions modules/connectIdSystem.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,12 @@ import {uspDataHandler} from '../src/adapterManager.js';
import {MODULE_TYPE_UID} from '../src/activities/modules.js';

const MODULE_NAME = 'connectId';
const STORAGE_EXPIRY_DAYS = 14;
const STORAGE_EXPIRY_DAYS = 365;
const STORAGE_DURATION = 60 * 60 * 24 * 1000 * STORAGE_EXPIRY_DAYS;
const ID_EXPIRY_DAYS = 14;
const VALID_ID_DURATION = 60 * 60 * 24 * 1000 * ID_EXPIRY_DAYS;
const PUID_EXPIRY_DAYS = 30;
const PUID_EXPIRY = 60 * 60 * 24 * 1000 * PUID_EXPIRY_DAYS;
const VENDOR_ID = 25;
const PLACEHOLDER = '__PIXEL_ID__';
const UPS_ENDPOINT = `https://ups.analytics.yahoo.com/ups/${PLACEHOLDER}/fed`;
Expand All @@ -28,11 +33,11 @@ export const storage = getStorageManager({moduleType: MODULE_TYPE_UID, moduleNam
* @param {Object} obj
*/
function storeObject(obj) {
const expires = Date.now() + (60 * 60 * 24 * 1000 * STORAGE_EXPIRY_DAYS);
const expires = Date.now() + STORAGE_DURATION;
if (storage.cookiesAreEnabled()) {
setEtldPlusOneCookie(MODULE_NAME, JSON.stringify(obj), new Date(expires), getSiteHostname());
} else if (storage.localStorageIsEnabled()) {
obj.__expires = expires;
}
if (storage.localStorageIsEnabled()) {
storage.setDataInLocalStorage(MODULE_NAME, JSON.stringify(obj));
}
}
Expand Down Expand Up @@ -75,7 +80,9 @@ function getIdFromLocalStorage() {
if (storedIdData) {
try {
storedIdData = JSON.parse(storedIdData);
} catch {}
} catch (e) {
logError(`${MODULE_NAME} module: error while reading the local storage data.`);
}
if (isPlainObject(storedIdData) && storedIdData.__expires &&
storedIdData.__expires <= Date.now()) {
storage.removeDataFromLocalStorage(MODULE_NAME);
Expand All @@ -87,6 +94,34 @@ function getIdFromLocalStorage() {
return null;
}

function syncLocalStorageToCookie() {
if (!storage.cookiesAreEnabled()) {
return;
}
const value = getIdFromLocalStorage();
const newCookieExpireTime = Date.now() + STORAGE_DURATION;
setEtldPlusOneCookie(MODULE_NAME, JSON.stringify(value), new Date(newCookieExpireTime), getSiteHostname());
}

function isStale(storedIdData) {
if (isPlainObject(storedIdData) && storedIdData.lastSynced &&
(storedIdData.lastSynced + VALID_ID_DURATION) <= Date.now()) {
return true;
}
return false;
}

function getStoredId() {
let storedId = getIdFromCookie();
if (!storedId) {
storedId = getIdFromLocalStorage();
if (storedId && !isStale(storedId)) {
syncLocalStorageToCookie();
}
}
return storedId;
}

function getSiteHostname() {
const pageInfo = parseUrl(getRefererInfo().page);
return pageInfo.hostname;
Expand Down Expand Up @@ -127,16 +162,31 @@ export const connectIdSubmodule = {
return;
}
const params = config.params || {};
if (!params || (typeof params.he !== 'string' && typeof params.puid !== 'string') ||
if (!params ||
(typeof params.pixelId === 'undefined' && typeof params.endpoint === 'undefined')) {
logError(`${MODULE_NAME} module: configurataion requires the 'pixelId' and at ` +
`least one of the 'he' or 'puid' parameters to be defined.`);
logError(`${MODULE_NAME} module: configuration requires the 'pixelId'.`);
return;
}

const storedId = getIdFromCookie() || getIdFromLocalStorage();
const storedId = getStoredId();

let shouldResync = isStale(storedId);

if (storedId) {
return {id: storedId};
if (isPlainObject(storedId) && storedId.puid && storedId.lastUsed && !params.puid &&
(storedId.lastUsed + PUID_EXPIRY) <= Date.now()) {
delete storedId.puid;
shouldResync = true;
}
if ((params.he && params.he !== storedId.he) ||
(params.puid && params.puid !== storedId.puid)) {
shouldResync = true;
}
if (!shouldResync) {
storedId.lastUsed = Date.now();
storeObject(storedId);
return {id: storedId};
}
}

const uspString = uspDataHandler.getConsentData() || '';
Expand All @@ -159,14 +209,27 @@ export const connectIdSubmodule = {
}
});

const hashedEmail = params.he || storedId?.he;
if (hashedEmail) {
data.he = hashedEmail;
}
if (!data.puid && storedId?.puid) {
data.puid = storedId.puid;
}

const resp = function (callback) {
const callbacks = {
success: response => {
let responseObj;
if (response) {
try {
responseObj = JSON.parse(response);
if (isPlainObject(responseObj) && Object.keys(responseObj).length > 0) {
if (isPlainObject(responseObj) && Object.keys(responseObj).length > 0 &&
(!!responseObj.connectId || !!responseObj.connectid)) {
responseObj.he = params.he;
responseObj.puid = params.puid || responseObj.puid;
responseObj.lastSynced = Date.now();
responseObj.lastUsed = Date.now();
storeObject(responseObj);
} else {
logError(`${MODULE_NAME} module: UPS response returned an invalid payload ${response}`);
Expand All @@ -186,7 +249,12 @@ export const connectIdSubmodule = {
let url = `${params.endpoint || endpoint}?${formatQS(data)}`;
connectIdSubmodule.getAjaxFn()(url, callbacks, null, {method: 'GET', withCredentials: true});
};
return {callback: resp};
const result = {callback: resp};
if (shouldResync && storedId) {
result.id = storedId;
}

return result;
},

/**
Expand Down
11 changes: 4 additions & 7 deletions modules/connectIdSystem.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,15 @@

Yahoo ConnectID user ID Module.

*Note: The storage config should be ommited as the module handles the storage of the needed information.

### Prebid Params

```
pbjs.setConfig({
userSync: {
userIds: [{
name: 'connectId',
storage: {
name: 'connectId',
type: 'html5',
expires: 15
},
params: {
pixelId: 58776,
he: '0bef996248d63cea1529cb86de31e9547a712d9f380146e98bbd39beec70355a'
Expand All @@ -31,5 +28,5 @@ The below parameters apply only to the Yahoo ConnectID user ID Module.
| params | Required | Object | Container of all module params. ||
| params.pixelId | Required | Number |
The Yahoo-supplied publisher-specific pixel ID. | `"0000"` |
| params.he | Optional | String | The SHA-256 hashed user email address which has been lowercased prior to hashing. Pass both `he` and `puid` params if present, otherwise pass either of the two that is available. |`"ed8ddbf5a171981db8ef938596ca297d5e3f84bcc280041c5880dba3baf9c1d4"`|
| params.puid | Optional | String | The publisher supplied user identifier such as a first-party cookie. Pass both `he` and `puid` params if present, otherwise pass either of the two that is available. | `"ab9iibf5a231ii1db8ef911596ca297d5e3f84biii00041c5880dba3baf9c1da"` |
| params.he | Optional | String | The SHA-256 hashed user email address which has been lowercased prior to hashing. |`"ed8ddbf5a171981db8ef938596ca297d5e3f84bcc280041c5880dba3baf9c1d4"`|
| params.puid | Optional | String | A domain-specific user identifier such as a first-party cookie. If not passed, a puid value will be auto-generated and stored in local and / or cookie storage. | `"ab9iibf5a231ii1db8ef911596ca297d5e3f84biii00041c5880dba3baf9c1da"` |
Loading