forked from prebid/Prebid.js
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
lockr AIM user module: initial release (prebid#11159)
* Adding Lockr AIM module and tests * formatting * Fix formatting * format * fix formatting * add paapi back * added markdown file * 20240324 Fixed Storage Manager | lockrAIMIdSystem.js * Updated to use Prebid Storage Manager | lockrAIMIdSystem_shared.js * added the fix for the comments * removed the unnecessary console --------- Co-authored-by: chris-lockr <[email protected]> Co-authored-by: avin-lockr <[email protected]>
- Loading branch information
1 parent
51c63b6
commit 0e58601
Showing
4 changed files
with
409 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,165 @@ | ||
/** | ||
* This module adds lockr AIM ID support to the User ID module | ||
* The {@link module:modules/userId} module is required. | ||
* @module modules/lockrAIMIdSystem | ||
* @requires module:modules/userId | ||
*/ | ||
|
||
import { submodule } from '../src/hook.js'; | ||
import { ajax } from '../src/ajax.js'; | ||
import { logInfo, logWarn } from '../src/utils.js'; | ||
import { getStorageManager } from '../src/storageManager.js'; | ||
import { MODULE_TYPE_UID } from '../src/activities/modules.js'; | ||
import { gppDataHandler } from '../src/adapterManager.js'; | ||
|
||
/** | ||
* @typedef {import('../modules/userId/index.js').Submodule} Submodule | ||
* @typedef {import('../modules/userId/index.js').SubmoduleConfig} SubmoduleConfig | ||
* @typedef {import('../modules/userId/index.js').ConsentData} ConsentData | ||
* @typedef {import('../modules/userId/index.js').lockrAIMId} lockrAIMId | ||
*/ | ||
|
||
const MODULE_NAME = 'lockrAIMId' | ||
const LOG_PRE_FIX = 'lockr-AIM: '; | ||
|
||
const AIM_PROD_URL = 'https://identity.loc.kr'; | ||
|
||
export const lockrAIMCodeVersion = '1.0'; | ||
|
||
export const storage = getStorageManager({ moduleType: MODULE_TYPE_UID, moduleName: MODULE_NAME }) | ||
|
||
function createLogger(logger, prefix) { | ||
return function (...strings) { | ||
logger(prefix + ' ', ...strings); | ||
} | ||
} | ||
|
||
const _logInfo = createLogger(logInfo, LOG_PRE_FIX); | ||
const _logWarn = createLogger(logWarn, LOG_PRE_FIX); | ||
|
||
/** @type {Submodule} */ | ||
export const lockrAIMSubmodule = { | ||
/** | ||
* used to link submodule with config | ||
* @type {string} | ||
*/ | ||
name: MODULE_NAME, | ||
|
||
init() { | ||
_logInfo('lockrAIM Initialization complete'); | ||
}, | ||
|
||
/** | ||
* performs action to obtain id and return a value. | ||
* @function | ||
* @param {SubmoduleConfig} [config] | ||
* @param {ConsentData|undefined} consentData | ||
* @returns {lockrAIMId} | ||
*/ | ||
getId(config, consentData) { | ||
if (consentData?.gdprApplies === true) { | ||
_logWarn('lockrAIM is not intended for use where GDPR applies. The lockrAIM module will not run'); | ||
return undefined; | ||
} | ||
|
||
const gppConsent = gppDataHandler.getConsentData(); | ||
let gppString = ''; | ||
if (gppConsent) { | ||
gppString = gppConsent.gppString; | ||
} | ||
const mappedConfig = { | ||
appID: config?.params?.appID, | ||
email: config?.params?.email, | ||
baseUrl: AIM_PROD_URL, | ||
}; | ||
|
||
_logInfo('lockr AIM configurations loaded and mapped.', mappedConfig); | ||
if (!mappedConfig.appID || !mappedConfig.email) { | ||
return undefined; | ||
} | ||
const tokenGenerator = new LockrAIMApiClient(mappedConfig, _logInfo, _logWarn, storage, gppString); | ||
const result = tokenGenerator.generateToken(); | ||
_logInfo('lockr AIM results generated'); | ||
return result; | ||
} | ||
} | ||
|
||
class LockrAIMApiClient { | ||
static expiryDateKeys = []; | ||
static canRefreshToken = false; | ||
|
||
constructor(opts, logInfo, logWarn, prebidStorageManager, gppString) { | ||
this._baseUrl = opts.baseUrl; | ||
this._appID = opts.appID; | ||
this._email = opts.email; | ||
this._logInfo = logInfo; | ||
this._logWarn = logWarn; | ||
this._gppString = gppString; | ||
this.prebidStorageManager = prebidStorageManager; | ||
LockrAIMApiClient.expiryDateKeys = this.prebidStorageManager.getDataFromLocalStorage('lockr_expiry_keys') ? JSON.parse(this.prebidStorageManager.getDataFromLocalStorage('lockr_expiry_keys')) : [] | ||
this.initializeRefresher(); | ||
} | ||
|
||
async generateToken(type = 'email', value) { | ||
const url = this._baseUrl + '/publisher/app/v1/identityLockr/generate-tokens'; | ||
let rejectPromise; | ||
const promise = new Promise((resolve, reject) => { | ||
rejectPromise = reject; | ||
}); | ||
const requestBody = { | ||
appID: this._appID, | ||
data: { | ||
type: type, | ||
value: value ?? this._email, | ||
gppString: this._gppString, | ||
} | ||
} | ||
this._logInfo('Sending the token generation request') | ||
ajax(url, { | ||
success: (responseText) => { | ||
try { | ||
const response = JSON.parse(responseText); | ||
LockrAIMApiClient.canRefreshToken = false; | ||
const token = response.lockrMappingToken; | ||
this.prebidStorageManager.setDataInLocalStorage('ilui', token); | ||
response.data.forEach(cookieitem => { | ||
const settings = cookieitem?.settings; | ||
this.prebidStorageManager.setDataInLocalStorage(`${cookieitem.key_name}_expiry`, cookieitem.identity_expires); | ||
if (!LockrAIMApiClient.expiryDateKeys.includes(`${cookieitem.key_name}_expiry`)) { | ||
LockrAIMApiClient.expiryDateKeys.push(`${cookieitem.key_name}_expiry`); | ||
} | ||
this.prebidStorageManager.setDataInLocalStorage('lockr_expiry_keys', JSON.stringify(LockrAIMApiClient.expiryDateKeys)); | ||
if (!settings?.dropLocalStorage) { | ||
this.prebidStorageManager.setDataInLocalStorage(cookieitem.key_name, cookieitem.advertising_token); | ||
} | ||
if (!settings?.dropCookie) { | ||
this.prebidStorageManager.setCookie(cookieitem.key_name, cookieitem.advertising_token); | ||
} | ||
}); | ||
LockrAIMApiClient.canRefreshToken = true; | ||
return; | ||
} catch (_err) { | ||
this._logWarn(_err); | ||
rejectPromise(responseText); | ||
LockrAIMApiClient.canRefreshToken = true; | ||
} | ||
} | ||
}, JSON.stringify(requestBody), { method: 'POST', contentType: 'application/json;charset=UTF-8' }); | ||
return promise; | ||
} | ||
|
||
async initializeRefresher() { | ||
setInterval(() => { | ||
LockrAIMApiClient.expiryDateKeys.forEach(expiryItem => { | ||
const currentMillis = new Date().getTime(); | ||
const dateMillis = this.prebidStorageManager.getDataFromLocalStorage(expiryItem); | ||
if (currentMillis > dateMillis && dateMillis !== null && this.prebidStorageManager.getDataFromLocalStorage('ilui') && LockrAIMApiClient.canRefreshToken) { | ||
this.generateToken('refresh', this.prebidStorageManager.getDataFromLocalStorage('ilui')); | ||
} | ||
}) | ||
}, 1000); | ||
} | ||
} | ||
|
||
// Register submodule for userId | ||
submodule('userId', lockrAIMSubmodule); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,165 @@ | ||
## **lockr AIM** | ||
|
||
Alternative Identity Manager (AIM) is a unified container for identity and data management. | ||
With AIM’s self-service platform, publishers seamlessly integrate and activate alternative IDs like LiveRamp’s Authenticated Traffic Solution (ATS), Unified ID 2.0 (UID2), ID5 and more. The burden of due diligence and maintenance, coupled with the benefits of server-side calls result in the adoption of multiple alternative IDs, clean rooms like InfoSum and CDPs like Blueconic based on their specific needs. | ||
|
||
### **Account Creation | AIM** | ||
|
||
Sign up for an [Identity lockr account.](https://sso.loc.kr/console/signup) | ||
Setup your app and activate the AIM library. | ||
Compile Prebid with the appropriate configurations, and deploy. | ||
|
||
### **Configuration | AIM** | ||
|
||
First, make sure to add the lockr’s AIM submodule to your Prebid.js package with: | ||
The following configuration parameters are available: | ||
AIM supports all Single Sign On functions, newsletter registrations, UTM parameters, etc. For the sake of clarity, a few examples are shared below. | ||
**Google oAuth: ** | ||
If you are using Google oAuth (_as an example_), the onSignIn function will subsequently call window.lockr.setAdditionalData function and include a raw email. | ||
|
||
``` | ||
function onSignIn(googleUser) { | ||
pbjs.setConfig({ | ||
userSync: { | ||
userIds: [{ | ||
name: 'lockrAIMId', | ||
params: { | ||
email: '[email protected]', | ||
appID: 'e84afc5f-4adf-4144-949f-1de5bd151fcc' | ||
} | ||
}] | ||
} | ||
}); | ||
} | ||
``` | ||
|
||
**Facebook oAuth:** | ||
If you are using Facebook Login (_as an example_), the statusChangeCallback function will subsequently call window.lockr.setAdditionalData function and include a raw email. | ||
|
||
``` | ||
function statusChangeCallback(response) { | ||
console.log('statusChangeCallback'); | ||
console.log(response); | ||
if(response.status === 'connected'){ | ||
pbjs.setConfig({ | ||
userSync: { | ||
userIds: [{ | ||
name: 'lockrAIMId', | ||
params: { | ||
email: '[email protected]', | ||
appID: 'e84afc5f-4adf-4144-949f-1de5bd151fcc' | ||
} | ||
}] | ||
} | ||
}); | ||
}else{ | ||
document.getElementById('status').innerHTML = 'Please login'; | ||
} | ||
} | ||
``` | ||
|
||
**Note:** The above code can be triggered from anywhere on the domain (i.e. a subscription form). | ||
|
||
<table> | ||
<tr> | ||
<td><strong>Param</strong> | ||
</td> | ||
<td><strong>Scope</strong> | ||
</td> | ||
<td><strong>Type</strong> | ||
</td> | ||
<td><strong>Description</strong> | ||
</td> | ||
<td><strong>Example</strong> | ||
</td> | ||
</tr> | ||
<tr> | ||
<td>name | ||
</td> | ||
<td>Required | ||
</td> | ||
<td>String | ||
</td> | ||
<td>The name of this module: <code>"lockrAIMId"</code> | ||
</td> | ||
<td><code>"lockrAIMId"</code> | ||
</td> | ||
</tr> | ||
<tr> | ||
<td>params | ||
</td> | ||
<td>Required | ||
</td> | ||
<td>Object | ||
</td> | ||
<td>Details for the configuration. | ||
</td> | ||
<td> | ||
</td> | ||
</tr> | ||
<tr> | ||
<td>params.email | ||
</td> | ||
<td>Required | ||
</td> | ||
<td>String | ||
</td> | ||
<td>Email address for identity tokens. | ||
</td> | ||
<td><code>[email protected]</code> | ||
</td> | ||
</tr> | ||
<tr> | ||
<td>params.appID | ||
</td> | ||
<td>Required | ||
</td> | ||
<td>String | ||
</td> | ||
<td>Identity lockr appID | ||
</td> | ||
<td><code>[email protected]</code> | ||
</td> | ||
</tr> | ||
</table> | ||
|
||
**lockr AIM Example** | ||
|
||
``` | ||
pbjs.setConfig({ | ||
userSync: { | ||
userIds: [{ | ||
name: 'lockrAIMId', | ||
params: { | ||
email: '[email protected]', | ||
appID: 'e84afc5f-4adf-4144-949f-1de5bd151fcc' | ||
} | ||
}] | ||
} | ||
}); | ||
``` | ||
|
||
_Note_: lockr’s AIM self-service interface empowers publishers with the ability to pass the alternative IDs activated back to the client as local storage or as a first party cookie. Each Identity Provider can be individually set to restrict from client-side delivery and instead be retained as an authentication event within Identity lockr. In this case no data is lost, but instead maintained for automated or manual sharing to any Data Endpoint. | ||
|
||
**Troubleshooting and Error handling:** | ||
|
||
1. Navigate to the domain where Prebid.js Library is integrated. | ||
2. Go to the 'Network' tab of your Developer Tools. Search for “prebid.js” | ||
3. In the application tab, you can confirm any activated Identity Provider (if client-side storage is turned on in AIM’s Identity Provider settings). | ||
4. Debugging: | ||
Enable the debug flag to true in the setConfig call: | ||
|
||
``` | ||
pbjs.setConfig({ | ||
debug: true, | ||
userSync: { | ||
userIds: [{ | ||
name: 'lockrAIMId', | ||
params: { | ||
email: '[email protected]', | ||
appID: 'e84afc5f-4adf-4144-949f-1de5bd151fcc' | ||
} | ||
}] | ||
} | ||
}); | ||
``` |
Oops, something went wrong.