関数を使用してUID2を生成する
この記事では、訪問関数を使用してユーザーのUID2を生成し、訪問プロファイルに保存する方法について説明します。
Unified ID 2.0 (UID2)は、The Tradedeskによって作成されたオープンソースのIDフレームワークで、サードパーティのクッキーの代わりに使用することができます。UID2は、ユーザーの個人情報(PII)を基にした確定的なユーザー識別子で、メールアドレスなどが該当します。UIDはハッシュ化され暗号化され、UID2リクエストのレスポンスで返されるUID2を作成します。詳細については、Tradedesk UID2 documentationを参照してください。
UID2は、The Tradedesk connectorや他のサポートされているアウトバウンドコネクタで使用することができます。
訪問プロファイルのUID2を生成する
UID2の生成には訪問関数を使用することを推奨します。訪問がPIIを持っているがUID2が割り当てられていない場合に関数をトリガーします。訪問関数についての詳細は、About event and visitor functionsを参照してください。
訪問関数は以下のような動作をします:
- 訪問がUID2を持っていない場合にUID2を生成します。
- UID2と
tealium_visitor_id
を含むイベントをTealium Collectに送信します。
関数から送信されたイベントによって、AudienceStream属性と訪問属性が豊かになります。
前提条件
UID2を生成する訪問関数を作成する前に、以下のことを行ってください:
-
The Tradedeskから受け取ったデータの属性を持つUID2イベント仕様を作成します(
uid_identifier
、uid2
、uid_timestamp
)。この関数は、このイベント仕様を使用してTealium Collectにイベントを送信します。例えば:
-
ユーザーを識別するためのPII属性を選択します。現在、UID2は電話番号またはメールアドレスの識別子をサポートしています。
-
UID2を保存するための訪問属性を作成します。この訪問属性をイベントのUID2属性の値でエンリッチするためのエンリッチメントを追加します。詳細については、Using AttributesとAbout enrichmentsを参照してください。
-
UID2が割り当てられていない識別された訪問(メールアドレス、電話番号、または他の識別子が割り当てられている訪問)のためのオーディエンスを作成します。例えば:
詳細については、Create an audienceを参照してください。
UID2生成関数
関数を作成する際には、以下のことを行ってください:
- トリガーとしてProcessed Visitorを選択します。
- Audienceでは、UID2が割り当てられていない識別された訪問のために作成したオーディエンスを選択します。Trigger Onはデフォルト値のままにしておきます。これは
Joined Audience
です。
処理済み訪問関数のデフォルトコードを削除し、Example codeで示されているUID2を生成するための例示コードをコピーして貼り付けます。必要に応じて例示コードを修正します。 - Advancedタブをクリックし、Assign Authenticationsをクリックして、関数にUID2認証を追加します。
詳細については、Add UID2 Authenticationを参照してください。
例示コード
この例示コードは、訪問にUID2を割り当てるための関数を構成するためのガイドであり、修正せずには使用できません。コード内のTODO
と記述されているコメントを探し、あなたの構成に合わせて修正する必要がある行を探してください。
この例では、ユーザー識別子としてメールアドレスを使用していますが、他のユーザー識別子を使用するように適応することができます。属性IDは、メール属性の値を取得するために使用されます。属性IDを、使用している属性の正しい値に更新してください。
import CryptoES from 'crypto-es'
activate(async ({ visitor, visit, helper }) => {
const genHash = (data) => {
return CryptoES.SHA256(data).toString(CryptoES.enc.Base64)
}
const validateEmail = (email) => {
return String(email)
.toLowerCase()
.match(
/^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|.(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/
);
};
let tealium_config = {
tealium_account: 'CURRENT',
tealium_profile: 'CURRENT',
tealium_datasource: 'DATA_SOURCE_KEY', // TODO: DATA_SOURCE_KEYをあなたのTealium Data Sourceキーに変更します。
email_hashed: false // TODO: メールがすでにハッシュ化されている場合は、これをtrueに構成します。
};
if(tealium_config.tealium_account == 'CURRENT') {
tealium_config.tealium_account = visitor.properties.account
}
if(tealium_config.tealium_profile == 'CURRENT') {
tealium_config.tealium_profile = visitor.properties.profile
}
// TODO: attribute_numberを訪問のメールが格納されている属性を指すように変更します
const email = visitor.getAttributeValueById('ATTRIBUTE_ID')
let hashed_email = '';
console.log(email)
const tealium_vid = visitor.properties.visitor_id
if(!tealium_config.email_hashed) {
if(!validateEmail(email)) {
throw new Error(`Email Attribute is not a valid email`);
return false
}
hashed_email = genHash(email)
} else {
hashed_email = email
}
console.log(hashed_email)
// TODO: 以下の変数をあなたのTTD UID2の認証情報に更新します
const api_key = 'TTD_API_KEY' // TODO: TTD_API_KEYをあなたのTTD APIキーに変更します。
const secret = 'UID2_SECRET' // TODO: UID2_SECRETをあなたのTTD UID2の秘密に変更します。
const url = 'https://prod.uidapi.com/v2/identity/map'
const key = CryptoES.enc.Base64.parse(secret)
const hexRef = "0123456789abcdef"
const randomBytes = (bytes) => {
let buf = ''
for (let i = 0; i < bytes * 2; i++)
buf += hexRef.charAt(Math.floor(Math.random() * hexRef.length))
return buf
}
const writeBigUint64BE = (num, bytes = 8) => {
let buf = num.toString(16)
let padding = ''
for (let i = 0; i < bytes * 2 - buf.length; i++)
padding += '0'
return padding + buf
}
const encrypt = (data) => {
const iv = randomBytes(12)
const nonce = randomBytes(8)
const millisec = Date.now()
const timestamp = writeBigUint64BE(millisec)
const payload = CryptoES.enc.Utf8.parse(JSON.stringify(data))
const body = timestamp + nonce + payload
const ivBuf = CryptoES.enc.Hex.parse(iv)
const encryptedBody = CryptoES.AES.encrypt(
CryptoES.enc.Hex.parse(body),
key,
{
iv: ivBuf,
mode: CryptoES.mode.GCM,
padding: CryptoES.pad.NoPadding
}
)
const ciphertext = encryptedBody.ciphertext
const authTag = CryptoES.mode.GCM.mac(CryptoES.algo.AES, key, ivBuf, null, ciphertext).toString()
const enveloped = '01' + iv + ciphertext.toString() + authTag
return {
timestamp: parseInt(timestamp, 16),
nonce: parseInt(nonce, 16),
enveloped: CryptoES.enc.Hex.parse(enveloped).toString(CryptoES.enc.Base64)
}
}
const decrypt = (data) => {
const buf = CryptoES.enc.Base64.parse(data).toString(CryptoES.enc.Hex)
const iv = CryptoES.enc.Hex.parse(buf.substring(0, 24))
const ciphertext = CryptoES.enc.Hex.parse(buf.substring(24, buf.length - 32))
const tag = buf.substring(buf.length - 32)
const encryptedBody = new CryptoES.lib.CipherParams({ ciphertext: ciphertext })
const decrypted = CryptoES.AES.decrypt(encryptedBody,key,
{
iv: iv,
mode: CryptoES.mode.GCM,
padding: CryptoES.pad.NoPadding
}
).toString()
const timestamp = decrypted.substring(0, 16)
const nonce = decrypted.substring(16, 32)
const developed = decrypted.substring(32)
return {
timestamp: parseInt(timestamp, 16),
nonce: parseInt(nonce, 16),
developed: JSON.parse(CryptoES.enc.Hex.parse(developed).toString(CryptoES.enc.Utf8))
}
}
const payload = {
email_hash: [genHash(email)]
}
const {timestamp, nonce, enveloped} = encrypt(payload)
console.log('\n********** 暗号化 **********')
console.log('timestamp:', timestamp)
console.log('nonce:', nonce)
console.log('enveloped:', enveloped)
const response = await fetch(url, {
method: 'POST',
body: enveloped,
headers: {
'Authorization': `Bearer ${api_key}`
}
})
if (response.status == 200) {
const body = await response.text()
console.log('\n********** 応答 **********')
console.log(body)
const data = decrypt(body)
console.log('\n********** 復号化 **********')
console.log('timeStamp:', data.timestamp)
console.log('nonce:', data.nonce)
console.log('response:', JSON.stringify(data.developed))
console.log('\n')
// TODO: このイベント仕様は、Functionの最後にTealiumに送信されます。作成したイベント仕様の属性がevent_dataの属性と一致していることを確認してください。
let event_data ={
tealium_event: "UID2_event_data",
tealium_visitor_id: tealium_vid,
uid: data.developed.body.mapped[0].advertising_id,
uid_timestamp : JSON.stringify(data.timestamp)
};
// これは、event_dataオブジェクトをTealiumに送信して処理するステップです。
console.log(JSON.stringify(event_data))
if(event_data.uid) {
track(event_data, tealium_config)
.then(response => {
if (!response.ok) {
throw new Error(`ネットワーク応答が正常ではありませんでした。ステータスコード: ${response.status}.`);
}
console.log('ステータスコード:', response.status);
return response.text();
})
.catch(error => console.error('エラー:', error.message));
}
else {
console.error("広告IDを生成できませんでした")
}
}
else {
console.log('\nxxxxx 失敗 xxxxx\n')
console.log(JSON.stringify(response))
}
})
最終更新日 :: 2024年December月18日