-
Notifications
You must be signed in to change notification settings - Fork 2.1k
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
lockr AIM user module: initial release #11159
Merged
Merged
Changes from 11 commits
Commits
Show all changes
12 commits
Select commit
Hold shift + click to select a range
1c6d5f7
Adding Lockr AIM module and tests
chris-lockr c840378
formatting
chris-lockr f2d72ce
Fix formatting
chris-lockr 6bdc534
format
chris-lockr bf640f6
fix formatting
chris-lockr fe8ed4f
add paapi back
chris-lockr 4c6d806
added markdown file
chris-lockr 553599a
20240324 Fixed Storage Manager | lockrAIMIdSystem.js
KEPlockr 1f59e76
Updated to use Prebid Storage Manager | lockrAIMIdSystem_shared.js
KEPlockr cd5bff8
added the fix for the comments
avin-lockr 320c5a1
removed the unnecessary console
avin-lockr 227c182
Merge branch 'master' into lockr-aim-user-module
avin-lockr File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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: 'john@example.com', | ||
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: 'john@example.com', | ||
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>test@example.com</code> | ||
</td> | ||
</tr> | ||
<tr> | ||
<td>params.appID | ||
</td> | ||
<td>Required | ||
</td> | ||
<td>String | ||
</td> | ||
<td>Identity lockr appID | ||
</td> | ||
<td><code>test@example.com</code> | ||
</td> | ||
</tr> | ||
</table> | ||
|
||
**lockr AIM Example** | ||
|
||
``` | ||
pbjs.setConfig({ | ||
userSync: { | ||
userIds: [{ | ||
name: 'lockrAIMId', | ||
params: { | ||
email: 'test@example.com', | ||
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: 'test@example.com', | ||
appID: 'e84afc5f-4adf-4144-949f-1de5bd151fcc' | ||
} | ||
}] | ||
} | ||
}); | ||
``` |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
do you want to pass your endpoint the gpp string?