Skip to content

IntimateMerger Analytics Adapter : initial release#21

Open
eknis wants to merge 12 commits intomasterfrom
im-analytics-adapter
Open

IntimateMerger Analytics Adapter : initial release#21
eknis wants to merge 12 commits intomasterfrom
im-analytics-adapter

Conversation

@eknis
Copy link
Member

@eknis eknis commented Dec 3, 2025

Type of change

  • Bugfix

  • Feature

  • New bidder adapter

  • Updated bidder adapter

  • Code style update (formatting, local variables)

  • Refactoring (no functional changes, no api changes)

  • Build related changes

  • CI related changes

  • Does this change affect user-facing APIs or examples documented on http://prebid.org?

  • Other

Description of change

Other information

@github-actions
Copy link

github-actions bot commented Dec 3, 2025

Tread carefully! This PR adds 1 linter error (possibly disabled through directives):

  • modules/imAnalyticsAdapter.js (+1 error)

@github-actions
Copy link

github-actions bot commented Dec 3, 2025

Tread carefully! This PR adds 1 linter error (possibly disabled through directives):

  • modules/imAnalyticsAdapter.js (+1 error)

@github-actions
Copy link

github-actions bot commented Dec 3, 2025

Tread carefully! This PR adds 1 linter error (possibly disabled through directives):

  • modules/imAnalyticsAdapter.js (+1 error)

@eknis eknis requested review from april418 and fecker December 4, 2025 07:11
@eknis eknis marked this pull request as ready for review December 4, 2025 07:11
Copy link
Member

@fecker fecker left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ちともろもろ確認したいのと、意識合わせしたいです。

各社のAnalytics Adaptor は、bid の分析をもろもろしているのですが、
IMでは不要なので、そのあたりは調整が必要かなと。

今の実装ならキャッシュは不要な気がしつつ、バッファリング送信機能をつけるなら必要になるかなと思っています。

  • AUCTION_INIT
    • cache の初期化(auctionId の管理用)
    • Consent データの初期化 (auctionId に紐づけて管理)
    • pvデータのみを送信(ちょっと悩み中。データとして使わないなら、ぶっちゃけまとめて送ってもいいかも? 調整中)
  • AUCTION_END
    • setTimeout で遅延実行(800 ms くらい?)
      • cache[auctionId] に入ってるものを送る
      • cache[auctionId] で、データ送信フラグ を管理
    • setTimeout で遅延実行(3分後くらい?)
      • cache[auctionId] を削除する
        − SPA でたまらないようにする
  • BID_WON
    • cache[auctionId] に 情報を蓄積する
    • データ送信済だったら(フラグがたってたら)全データを再送する

実装イメージ

case EVENTS.AUCTION_END:
  setTimeout(() => {
    analyticsAdapter.sendEvents(args.auctionId);
  }, BID_WON_WAIT); // 800ms ?
  break;

こんなことを書いてる Adaptor がいるので、バッファリングいけるんじゃないかと思ってます。

case EVENTS.BID_WON:
  const auction = cache.auctions[args.auctionId];
  if (!auction) return;

  // transactionId 単位で、cache するか
  // 配列に push した方が楽かもしれない

  // 再送を考えて、Timestamp も入れてもいいかも

  if (auction.sendStatus & REQUEST_SENT) { // すでに送信済だったら
     analyticsAdapter.sendEvents(args.auctionId); // 再送する
  }

みたいな感じでいけたりしないかなぁと思ってきました。

許諾のデータは、
libraries/intentIqUtils/getCmpData.js を参考にして
gdpr と usp (ccpa) だけとっておくと幸せになれるかなとおもってきました。

import { allConsent } from '../../src/consentHandler.js';

/**
 * Retrieves consent data from the Consent Management Platform (CMP).
 * @return {Object} An object containing the following fields:
 * - `gdprString` (string): GDPR consent string if available.
 * - `uspString` (string): USP consent string if available.
 * - `gppString` (string): GPP consent string if available.
 */
export function getCmpData() {
  const consentData = allConsent.getConsentData();

  return {
    gdprApplies: consentData?.gdpr?.gdprApplies || false,
    gdprString: typeof consentData?.gdpr?.consentString === 'string' ? consentData.gdpr.consentString : null,
    uspString: typeof consentData?.usp === 'string' ? consentData.usp : null,
    gppString: typeof consentData?.gpp?.gppString === 'string' ? consentData.gpp.gppString : null,
  };
}

@eknis
Copy link
Member Author

eknis commented Dec 9, 2025

時刻 0ms:   AUCTION_INIT
            ↓ sendStatus = 0
時刻 100ms: BID_WON #1
            ↓ sendStatus & WON_SENT = 0 → キャッシュに追加
時刻 200ms: BID_WON #2
            ↓ sendStatus & WON_SENT = 0 → キャッシュに追加
時刻 300ms: AUCTION_END
            ↓ 800msタイマー開始
時刻 1100ms: sendWonBidsData() 実行
             ↓ BID_WON #1, #2 をまとめて送信
             ↓ sendStatus |= WON_SENT → sendStatus = 1
時刻 1500ms: BID_WON #3(遅延)
             ↓ sendStatus & WON_SENT = 1 → 即座に個別送信
時刻 2000ms: BID_WON #4(遅延)
             ↓ sendStatus & WON_SENT = 1 → 即座に個別送信

@github-actions
Copy link

Tread carefully! This PR adds 2 linter errors (possibly disabled through directives):

  • modules/imAnalyticsAdapter.js (+2 errors)

@github-actions
Copy link

Tread carefully! This PR adds 2 linter errors (possibly disabled through directives):

  • modules/imAnalyticsAdapter.js (+2 errors)

@github-actions
Copy link

Tread carefully! This PR adds 2 linter errors (possibly disabled through directives):

  • modules/imAnalyticsAdapter.js (+2 errors)

@eknis eknis requested a review from fecker December 25, 2025 05:51
Copy link
Member

@fecker fecker left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

空いちゃってしません。直してリリースしましょう。

Comment on lines +92 to +93
gdprApplies: gdprConsent.gdprApplies,
gdpr: gdprConsent.consentString,
Copy link
Member

@fecker fecker Mar 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

gdpr の consent はいらないかなと思ってきました・・・・(対応するつもりがほぼない)
他の adapter でやってたのですが gdpr に true / false (gdprApplies) を渡して、あげるのが幸せになれるかと思いました。

return {
gdprApplies: gdprConsent.gdprApplies,
gdpr: gdprConsent.consentString,
usp: uspConsent
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

coppa も念の為取得しておいて頂けるとうれしいです。
coppa = Number(coppaDataHandler.getCoppa());

const gdprConsent = request.gdprConsent || {};
const uspConsent = request.uspConsent;

return {
Copy link
Member

@fecker fecker Mar 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

アメリカ・カナダがそこそこ入っていたので、
ggp: gppDataHandler.getConsentData().applicableSections; (Number が入ります)
ggpString: gppDataHandler.getConsentData().gppString;
で取得をお願いします。
(真面目にやるとここを見るのが良さげ?)


case EVENTS.AUCTION_END:
logMessage('IM Analytics: AUCTION_END', args);
this.scheduleWonBidsSend(args.auctionId);
Copy link
Member

@fecker fecker Mar 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

細かいのですが、handleActionEnd() の方が良いのかなと思ったり。
で、その中で 2つの処理を schedule するのが良いのでは?って思いました。

別のAdapterでやってたのですが、
(あまりユースケースはないかもですが、)Cache の肥大化対策をしてるものがいました。

一定時間後(5秒 〜 10秒後)に、cache[auctions] をクリアする処理があってもいいかもす。

* @param {Object} auctionArgs - Auction arguments
* @param {Object} consentData - Consent data object
*/
handleAucInitData(auctionArgs, consentData) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

consentData って、auction の中でキャッシュされてるので、それを使いまわした方が良いのではと思ったのですが、どうすか?

handleAuction で、引数があわないのが気持ちわるい感じがします。

*/
transformAucInitData(auctionArgs) {
return {
timestamp: auctionArgs.timestamp,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

細かいですが、ボリュームが増えるので、short にした方がエコかもです。
(僕なら ts とかにしちゃいます w)

Comment on lines +183 to +184
pageUrl: window.location.href,
referrer: document.referrer || '',
Copy link
Member

@fecker fecker Mar 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

細かいですが、url とか短くしちゃって良いかなと。少しでもネットワークコストを下げる的な。
(まぁ、payload なので圧縮かかるかなと思いつつ)

return;
}

const consentData = auction.consentData || getConsentData(null);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cache からとるだけで大丈夫なんじゃないかなって思いました。

*/
sendWonBidsData(auctionId) {
const auction = cache.auctions[auctionId];
if (!auction || !auction.wonBids || auction.wonBids.length === 0 || (auction.sendStatus & WON_SENT)) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

全部一緒に送ることを考えると最後の条件はいらないかなと。
(送れてきても、全部一緒に送ることで集計が楽になるはず)の

});

// Clear cached bids after sending to prevent duplicates
auction.sendStatus |= WON_SENT;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

細かいですが、sendToApi する前に、セットした方が良かったりしますか?
(時間がかかったたときに微妙なので)の

Copy link
Member

@fecker fecker left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

遅くなってすいません。リリースに向かいましょう。

Comment on lines +82 to +86
function getConsentData(bidderRequests) {
if (!bidderRequests || !bidderRequests[0]) {
return EMPTY_CONSENT_DATA;
}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

bidderRequests から取るより、Adapter から取得した方が分かりやすいかなと思ったのですが、どっちがいいっすかね・・?(0番目から取るよりという意味で。他のAnalytics Adapter はどうですか?)

Comment on lines +285 to +286
timestamp,
wonBids: auction.wonBids
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

少しでも小さくと・・・ ts, bids あたりで良いかもです。


const DEFAULT_BID_WON_TIMEOUT = 800; // 0.8 second for initial batch
const DEFAULT_CID = 5126;
const API_BASE_URL = 'https://b6.im-apps.net/bids';
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(完全に趣味ですが)Prebid にあわせて、bid にしませんか?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants