คู่มือนักพัฒนาซอฟต์แวร์สำหรับสัญญาณแอปที่มีการป้องกัน

เอกสารนี้จะอธิบายถึง API ทั้งหมดภายในแพลตฟอร์มของ API, รายละเอียดวิธีตั้งค่าสภาพแวดล้อมการทดสอบ รวมถึงแสดงตัวอย่างการกำหนดค่าและสคริปต์ เพื่อช่วยนักพัฒนาแอปเริ่มการทดสอบกับ Protected App Signals API

ประวัติเวอร์ชัน

Jan 2024

คู่มือสำหรับนักพัฒนาซอฟต์แวร์รุ่นแรกที่รองรับการเผยแพร่ PAS MVP

มีนาคม 2024

การเปลี่ยนแปลงใน API เพื่อรองรับ Android API รุ่น M-2024-05 และคอมโพเนนต์ฝั่งเซิร์ฟเวอร์ในเดือนเมษายน 2024 การเปลี่ยนแปลงที่โดดเด่นที่สุด:

  • เพิ่มรายละเอียดเกี่ยวกับสิทธิ์ที่จำเป็นสำหรับ API ในอุปกรณ์
  • เพิ่มรายละเอียดเพิ่มเติมเกี่ยวกับการจัดการโควต้าสัญญาณในอุปกรณ์
  • อัปเดตลายเซ็น generateBid พร้อมการเปลี่ยนแปลงที่เกี่ยวข้องกับการดึงข้อมูลโฆษณาตามบริบทและการรองรับข้อมูลขาออก
  • อัปเดตเอกสารประกอบ reportWin รายการ รวมถึงการรองรับข้อมูลขาออก
  • อัปเดตเอกสารประกอบ Ad Retrieval API ที่เลิกรองรับการดึงข้อมูลโฆษณา BYOS และการบันทึก UDF การดึงข้อมูลโฆษณา

ภาพรวม API

แพลตฟอร์ม Protected Signals API ประกอบด้วย API ชุดย่อยที่แตกต่างกันในระบบต่างๆ ดังนี้

  • Android API
    • Signal Curation API ซึ่งประกอบด้วย
    • อัปเดต Signals API
    • API การเข้ารหัสสัญญาณ
    • API การสนับสนุนการประมูลที่มีการป้องกัน: ที่ SDK จะใช้เพื่อเรียกใช้การประมูลที่มีการคุ้มครองในเซิร์ฟเวอร์การเสนอราคาและการประมูล (B&A) ที่ใช้สัญญาณของแอปที่มีการป้องกัน
  • API ฝั่งเซิร์ฟเวอร์:
    • API การประมูลที่มีการป้องกัน: ชุดสคริปต์ JS ที่ทำงานในเซิร์ฟเวอร์การเสนอราคาและการประมูล API นี้ช่วยให้ผู้ขายและผู้ซื้อสามารถเขียนตรรกะในการใช้งานการประมูลที่มีการป้องกัน
    • Ad Retrieval API: มีหน้าที่ระบุรายชื่อโฆษณาที่เป็นตัวเลือกโดยพิจารณาจากข้อมูลตามบริบทและข้อมูลผู้ใช้ที่แสดงต่อเซิร์ฟเวอร์การเสนอราคาของผู้ซื้อ

ไคลเอ็นต์ Android

ในฝั่งไคลเอ็นต์ แพลตฟอร์มสัญญาณแอปที่ได้รับการคุ้มครองประกอบด้วย API ที่แตกต่างกัน 3 รายการ ได้แก่

  • อัปเดตสัญญาณ: Android System API เพื่อให้สามารถดูแลจัดการสัญญาณต่างๆ บนอุปกรณ์ได้
  • การเข้ารหัสสัญญาณ: JavaScript API เพื่อเตรียมสัญญาณที่จะส่งไปยังเซิร์ฟเวอร์ระหว่างการประมูล
  • การสนับสนุนการประมูลที่มีการคุ้มครอง: API สำหรับรองรับการดำเนินการประมูลที่มีการคุ้มครองในเซิร์ฟเวอร์การเสนอราคาและการประมูล API นี้ไม่ได้มีไว้สำหรับ สัญญาณของแอปที่มีการป้องกันเท่านั้น และใช้เพื่อรองรับการประมูลสำหรับ Protected Audience API ด้วย

อัปเดต Signals API

อัปเดตสัญญาณ API ช่วยให้เทคโนโลยีโฆษณาสามารถลงทะเบียนสัญญาณที่เกี่ยวข้องกับผู้ใช้และแอปในนามของผู้ซื้อ API ทำงานบนโมเดลการมอบสิทธิ์ ผู้เรียกใช้จะระบุ URI ที่เฟรมเวิร์กดึงสัญญาณที่เกี่ยวข้องและตรรกะเพื่อเข้ารหัสสัญญาณเหล่านั้นเพื่อใช้ในการประมูล

API ต้องการสิทธิ์ android.permission.ACCESS_ADSERVICES_PROTECTED_SIGNALS

updateSignals() API จะดึงออบเจ็กต์ JSON จาก URI ซึ่งอธิบายสัญญาณที่ควรเพิ่มหรือนำออก รวมถึงวิธีเตรียมสัญญาณเหล่านั้นสำหรับการประมูล

Executor executor = Executors.newCachedThreadPool();
ProtectedSignalsManager protectedSignalsManager
     =  ProtectedSignalsManager.get(context);

// Initialize a UpdateSignalsRequest
UpdateSignalsRequest updateSignalsRequest = new
  UpdateSignalsRequest.Builder(Uri.parse("https://example-adtech1.com/signals"))
      .build();

OutcomeReceiver<Object, Exception> outcomeReceiver = new OutcomeReceiver<Object, Exception>() {
  @Override
  public void onResult(Object o) {
    //Post-success actions
  }

  @Override
  public void onError(Exception error) {
    //Post-failure actions
  };

// Call updateSignals
protectedSignalsManager.updateSignals(updateSignalsRequest,
    executor,
    outcomeReceiver);

แพลตฟอร์มจะส่งคำขอ HTTPS ไปยัง URI ที่ระบุไว้ในคำขอเพื่อดึงข้อมูลการอัปเดตสัญญาณ นอกเหนือจากการอัปเดตสัญญาณแล้ว การตอบสนองอาจมีปลายทางที่โฮสต์ตรรกะการเข้ารหัสสำหรับการแปลงสัญญาณดิบเป็นเพย์โหลดที่เข้ารหัส การอัปเดตสัญญาณควรอยู่ในรูปแบบ JSON และมีคีย์ต่อไปนี้

คีย์ระดับบนสุดสำหรับออบเจ็กต์ JSON ต้องสอดคล้องกับคำสั่ง 1 ใน 5 ข้อต่อไปนี้

คีย์

คำอธิบาย

put

เพิ่มสัญญาณใหม่ โดยเขียนทับสัญญาณที่มีอยู่ด้วยคีย์เดียวกัน ค่า

สำหรับนี่คือออบเจ็กต์ JSON โดยที่คีย์เป็นสตริงพื้นฐาน 64 สตริงที่เกี่ยวข้องกับคีย์ที่จะใส่ และค่าเป็นสตริงพื้นฐาน 64 ที่สอดคล้องกับค่าที่จะใส่

append

เพิ่มสัญญาณใหม่ต่อท้ายอนุกรมเวลา และนำสัญญาณที่เก่าที่สุดออก

สัญญาณให้มีพื้นที่ว่างสำหรับรายการใหม่หากขนาดของชุดหนังสือเกินขีดจำกัดที่กำหนด ค่าสำหรับรายการนี้เป็นออบเจ็กต์ JSON โดยที่คีย์เป็นสตริงพื้นฐาน 64 สตริงที่เกี่ยวข้องกับคีย์ที่จะต่อท้าย และค่าเป็นออบเจ็กต์ที่มี 2 ช่อง ได้แก่ "values" และ "maxSignals"

"values": รายการสตริงฐาน 64 ที่สอดคล้องกับค่าสัญญาณที่จะเพิ่มต่อท้ายอนุกรมเวลา

"maxSignals": จำนวนค่าสูงสุดที่อนุญาตในอนุกรมเวลานี้ หาก

จำนวนสัญญาณปัจจุบันที่เชื่อมโยงกับคีย์สูงกว่า maxSignals สัญญาณที่เก่าที่สุดจะถูกนำออก โปรดทราบว่าคุณสามารถเพิ่มคีย์ที่เพิ่มด้วย put โปรดทราบว่าการเพิ่มค่าเกินจำนวนสูงสุดจะทำให้ไม่สำเร็จ

put_if_not_present

เพิ่มสัญญาณใหม่เฉพาะในกรณีที่ไม่มีสัญญาณที่มีอยู่ที่มีคีย์เดียวกัน ค่าสำหรับส่วนนี้คือออบเจ็กต์ JSON โดยที่คีย์เป็นสตริงพื้นฐาน 64 สตริงที่เกี่ยวข้องกับคีย์ที่จะใส่ และค่าเป็นสตริงพื้นฐาน 64 ที่สอดคล้องกับค่าที่จะใส่

remove

นำสัญญาณของคีย์ออก ค่าของสตริงนี้คือรายการสตริงพื้นฐาน 64 สตริงที่เกี่ยวข้องกับคีย์ของสัญญาณที่ควรลบ

update_encoder

ระบุการดำเนินการเพื่ออัปเดตปลายทางและ URI ที่ใช้ได้

เพื่อดึงตรรกะการเข้ารหัส คีย์ย่อยสำหรับระบุการดำเนินการอัปเดตคือ "action" และ

ค่าที่รองรับในขณะนี้คือ "REGISTER" ซึ่งจะลงทะเบียนปลายทางโปรแกรมเปลี่ยนไฟล์หากระบุไว้เป็นครั้งแรก หรือเขียนทับค่าที่มีอยู่ด้วยปลายทางที่ระบุใหม่ ต้องระบุปลายทางสำหรับการดำเนินการ "REGISTER" คีย์ย่อยเพื่อระบุปลายทางโปรแกรมเปลี่ยนไฟล์คือ "endpoint" และค่าคือ URI

สตริงสำหรับปลายทาง

ตัวอย่างคำขอ JSON จะมีลักษณะดังนี้

{
    "put": {
        "AAAAAQ==": "AAAAZQ==",
        "AAAAAg==": "AAAAZg=="
    },
    "append": {
        "AAAAAw==": {
            "values": [
                "AAAAZw=="
            ],
            "max_signals": 3
        }
    },
    "put_if_not_present": {
        "AAAABA==": "AAAAaQ==",
        "AAAABQ==": "AAAAag=="
    },
    "update_encoder": {
        "action": "REGISTER",
        "endpoint": "https://adtech1.com/Protected App Signals_encode_script.js"
    }
}

สัญญาณจะมีโควต้าในอุปกรณ์ตามลำดับ 10-15 Kb เมื่อเกินโควต้า PPAPI จะกำจัดสัญญาณออกโดยใช้กลยุทธ์ FIFO ขั้นตอนการปลดออกจะทำให้ใช้โควต้าเกินโควต้าเล็กน้อยในช่วงเวลาสั้นๆ เพื่อลดความถี่ในการปลดเปลื้อง

API การเข้ารหัสสัญญาณ

ผู้ซื้อจะต้องให้ฟังก์ชัน JavaScript ที่จะใช้ในการเข้ารหัสสัญญาณที่จัดเก็บไว้ในอุปกรณ์เพื่อส่งไปยังเซิร์ฟเวอร์ระหว่างการประมูลที่มีการคุ้มครอง ผู้ซื้อระบุสคริปต์นี้ได้โดยการเพิ่ม URL ที่ใช้คีย์ "update_encoder" ในการตอบกลับคำขอ UpdateSignal API สคริปต์จะมีลายเซ็นต่อไปนี้

function encodeSignals(signals, maxSize) {
  let result = new Uint8Array(maxSize);
  // first entry will contain the total size
  let size = 1;
  let keys = 0;
  
  for (const [key, values] of signals.entries()) {
    keys++;
    // In this encoding we only care about the first byte
    console.log("key " + keys + " is " + key)
    result[size++] = key[0];
    result[size++] = values.length;
    for(const value of values) {
      result[size++] = value.signal_value[0];
    }
  }
  result[0] = keys;
  
  return { 'status': 0, 'results': result.subarray(0, size)};
}

พารามิเตอร์ signals คือการแมปจากคีย์ในรูปแบบ UInt8Arrays ขนาด 4 ไปยังรายการออบเจ็กต์ Protected App Signals ออบเจ็กต์ Protected App Signals แต่ละรายการจะมี 3 ช่อง ดังนี้

  • signal_value: UInt8Array ที่แสดงค่าของสัญญาณ
  • creation_time: จำนวนที่แสดงเวลาที่สร้างสัญญาณในหน่วยวินาที
  • package_name: สตริงที่แสดงชื่อแพ็กเกจที่สร้างสัญญาณ

พารามิเตอร์ maxSize คือจำนวนที่อธิบายขนาดอาร์เรย์สูงสุดที่อนุญาตสำหรับเอาต์พุต

ฟังก์ชันควรแสดงออบเจ็กต์ที่มีช่อง 2 ช่อง ดังนี้

  • status: ควรเป็น 0 หากสคริปต์ทำงานสำเร็จ
  • results: ควรเป็นอาร์เรย์ UInt8Array ของความยาวน้อยกว่าหรือเท่ากับ maxSize ระบบจะส่งอาร์เรย์นี้ไปยังเซิร์ฟเวอร์ในระหว่างการประมูล และจัดเตรียมโดยสคริปต์ prepareDataForAdRetrieval

การเข้ารหัสจะทำให้เทคโนโลยีโฆษณามีระยะเริ่มต้นของวิศวกรรมฟีเจอร์ ซึ่งช่วยให้เทคโนโลยีโฆษณาทำการเปลี่ยนรูปแบบ เช่น การบีบอัดสัญญาณดิบให้เป็นเวอร์ชันที่ต่อกันตามตรรกะที่กำหนดเองได้ โปรดทราบว่าในระหว่างการประมูลที่มีการคุ้มครองซึ่งทำงานในสภาพแวดล้อมการดำเนินการที่เชื่อถือได้ (TEE) ตรรกะที่กำหนดเองของเทคโนโลยีโฆษณาจะมีสิทธิ์อ่านเพย์โหลดสัญญาณที่สร้างโดยการเข้ารหัส ตรรกะที่กําหนดเองหรือที่เรียกว่าฟังก์ชันที่กำหนดโดยผู้ใช้ (UDF) ที่ทำงานใน B&A TEE ของผู้ซื้อจะมีสิทธิ์เข้าถึงการอ่านสัญญาณที่เข้ารหัสและสัญญาณบริบทอื่นๆ ที่แอปของผู้เผยแพร่โฆษณาให้ไว้ทําการเลือกโฆษณา (การดึงข้อมูลโฆษณาและการเสนอราคา)

การเข้ารหัสสัญญาณ

ทุกๆ ชั่วโมง ผู้ซื้อที่ระบุตรรกะการเข้ารหัสกับสัญญาณที่ได้ลงทะเบียนไว้จะมีสัญญาณที่เข้ารหัสเป็นเพย์โหลดการประมูล อาร์เรย์ไบต์สำหรับเพย์โหลดการประมูลจะยังคงอยู่ในอุปกรณ์และมีการเข้ารหัส และผู้ขายจะรวบรวมโดยเป็นส่วนหนึ่งของข้อมูลการเลือกโฆษณาเพื่อรวมไว้ในการประมูลที่มีการป้องกัน สำหรับการทดสอบ คุณเรียกใช้การเข้ารหัสนี้นอกรอบรายชั่วโมงได้โดยเรียกใช้คำสั่งต่อไปนี้

adb shell cmd jobscheduler run -f com.google.android.adservices.api 29
การกำหนดเวอร์ชันตรรกะของโปรแกรมเปลี่ยนไฟล์

เมื่อมีการขอให้ดาวน์โหลดตรรกะโปรแกรมเปลี่ยนไฟล์ที่กำหนดเองของเทคโนโลยีโฆษณา ปลายทางเทคโนโลยีโฆษณาสามารถตอบกลับด้วยหมายเลขเวอร์ชันในส่วนหัวการตอบกลับ เวอร์ชันนี้จะยังคงอยู่กับตรรกะของโปรแกรมเปลี่ยนไฟล์ในอุปกรณ์ เมื่อเข้ารหัสสัญญาณดิบแล้ว เพย์โหลดที่เข้ารหัสจะคงอยู่พร้อมกับเวอร์ชันที่ใช้สำหรับการเข้ารหัส เวอร์ชันนี้จะส่งไปพร้อมกับเซิร์ฟเวอร์ B&A ระหว่างการประมูลที่มีการคุ้มครองด้วย เพื่อให้เทคโนโลยีโฆษณาปรับตรรกะการเสนอราคาและการเข้ารหัสตามเวอร์ชันได้

Response header for providing encoder version : X_ENCODER_VERSION

API การสนับสนุนการประมูลที่มีการป้องกัน

ทางฝั่งอุปกรณ์ การประมูลสำหรับสัญญาณของแอปที่ได้รับการคุ้มครองจะเหมือนกับการประมูลสำหรับกลุ่มเป้าหมายที่ได้รับการคุ้มครอง

การเสนอราคาและบริการประมูล

API ฝั่งเซิร์ฟเวอร์ ได้แก่

  • API การประมูลที่มีการป้องกัน: ชุดฟังก์ชัน JS หรือ UDF ที่ผู้ซื้อและผู้ขายสามารถนำไปใช้งานในองค์ประกอบ B&A ที่ตนเป็นเจ้าของ เพื่อกำหนดตรรกะการเสนอราคาและการประมูล
  • API การดึงข้อมูลโฆษณา: ผู้ซื้อใช้งาน API นี้ได้โดยใช้ปลายทาง REST ซึ่งจะรับผิดชอบการจัดเตรียมชุดโฆษณาที่เป็นตัวเลือกในการประมูลสัญญาณแอปที่ได้รับการคุ้มครอง

API การประมูลที่มีการป้องกัน

Protectedการประมูลส่วนตัว API ประกอบด้วย JS API หรือ UDF ที่ผู้ซื้อและผู้ขายสามารถใช้ตรรกะของการประมูลและการเสนอราคาเพื่อนำมาใช้

UDF ของเทคโนโลยีโฆษณาของผู้ซื้อ
PreDataForAdRetrieval UDF

ก่อนที่จะสามารถใช้สัญญาณแอปที่ได้รับการคุ้มครองเพื่อดึงตัวเลือกโฆษณาจากบริการดึงข้อมูลโฆษณา TEE ผู้ซื้อต้องถอดรหัสและเตรียมสัญญาณแอปที่ได้รับการคุ้มครองและข้อมูลอื่นๆ ที่ผู้ขายให้ไว้ ระบบจะส่งเอาต์พุต UDF ของผู้ซื้อ prepareDataForAdRetrieval ไปยังบริการดึงข้อมูลโฆษณาเพื่อให้ดึงข้อมูลโฆษณาที่เป็นตัวเลือกยอดนิยมสําหรับการเสนอราคา

// Inputs
// ------
// encodedOnDeviceSignals: A Uint8Array of bytes from the device.
// encodedOnDeviceSignalsVersion: An integer representing the encoded
//   version of the signals.
// sellerAuctionSignals: Information about auction (ad format, size) derived
//                       contextually.
// contextualSignals: Additional contextual signals that could help in
//                    generating bids.
//
// Outputs
// -------
// Returns a JSON structure to be used for retrieval.
// The structure of this object is left to the adtech.
function prepareDataForAdRetrieval(encodedOnDeviceSignals,encodedOnDeviceSignalsVersion,sellerAuctionSignals,contextualSignals) {
   return {};
}
UDF ของ generateBid

หลังจากส่งคืนโฆษณาที่เป็นตัวเลือกยอดนิยมแล้ว ระบบจะส่งตัวเลือกโฆษณาไปยังตรรกะการเสนอราคาที่กำหนดเองของผู้ซื้อ generateBid UDF ดังนี้

// Inputs
// ------
// ads: Data string returned by the ads retrieval service. This can include Protected App Signals
//   ads and related ads metadata.
// sellerAuctionSignals: Information about the auction (ad format, size),
//                       derived contextually
// buyerSignals: Any additional contextual information provided by the buyer
// preprocessedDataForRetrieval: This is the output of this UDF.
function generateBid(ads, sellerAuctionSignals, buyerSignals,
                    preprocessedDataForRetrieval,
                    rawSignals, rawSignalsVersion) {
    return { "ad": <ad Value Object>,
             "bid": <float>,
             "render": <render URL string>,
             'adCost': <optional float ad cost>,
             "egressPayload": <limitedEgressPayload>,
             "temporaryUnlimitedEgressPayload": <temporaryUnlimitedEgressPayload>
    };
}

ผลลัพธ์ของฟังก์ชันนี้คือราคาเสนอเดียวสำหรับตัวเลือกโฆษณา ซึ่งแสดงเป็น JSON เทียบเท่ากับ ProtectedAppSignalsAdWithBidMetadata ฟังก์ชันนี้อาจแสดงผล 2 อาร์เรย์ที่จะส่งไปยัง reportWin เพื่อเปิดใช้การฝึกโมเดลด้วย (ดูรายละเอียดเพิ่มเติมเกี่ยวกับข้อมูลขาออกและการฝึกโมเดลได้ที่ส่วนการรายงานในตัวอธิบาย PAS)

รายงาน Win UDF

เมื่อการประมูลสิ้นสุดลง บริการการประมูลจะสร้าง URL การรายงานสําหรับผู้ซื้อและลงทะเบียนบีคอนโดยใช้ reportWin UDF (ซึ่งคือฟังก์ชัน reportWin เดียวกับที่ใช้สําหรับกลุ่มเป้าหมายที่มีการป้องกัน) โดยอุปกรณ์จะใช้คำสั่ง ping กับโฆษณาเมื่อไคลเอ็นต์แสดงโฆษณาแล้ว ลายเซ็นของวิธีนี้คล้ายกับเวอร์ชัน Protected Audience เกือบทั้งหมด ยกเว้นพารามิเตอร์เพิ่มเติม 2 รายการ egressPayload และ temporaryUnlimitedEgressPayload ที่ใช้เปิดใช้การฝึกโมเดลและป้อนข้อมูลผลลัพธ์จาก generateBid

// Inputs / Outputs
// ----------------
// See detailed documentation here.
function reportWin(auctionSignals, perBuyerSignals, signalsForWinner,
                   buyerReportingSignals,
                   egressPayload, temporaryUnlimitedEgressPayload) {
  // ...
}
UDF เทคโนโลยีโฆษณาของผู้ขาย
ScoreAd UDF

ผู้ขายใช้ UDF นี้เพื่อเลือกโฆษณาที่ได้รับจากผู้ซื้อที่จะชนะการประมูล

function scoreAd(adMetadata, bid, auctionConfig,
                 trustedScoringSignals, bid_metadata) {
  // ...
  return {desirability: desirabilityScoreForThisAd,
              allowComponentAuction: true_or_false};
}
UDF ผลลัพธ์รายงาน

UDF นี้อนุญาตให้ผู้ขายสามารถรายงานระดับเหตุการณ์ด้วยข้อมูลเกี่ยวกับโฆษณาที่ชนะ (ในท้ายที่สุด)

function reportResult(auctionConfig, reporting_metadata) {
  // ...
  registerAdBeacon({"click", clickUrl,"view", viewUrl});
  sendReportTo(reportResultUrl);
  return signalsForWinner;
}

API การดึงข้อมูลโฆษณา

ใน รุ่น MVP บริการดึงข้อมูลโฆษณาจะเป็นบริการที่จัดการโดยผู้ซื้อและโฮสต์ และบริการเสนอราคาจะดึงตัวเลือกโฆษณาจากบริการนี้ ตั้งแต่เดือนเมษายน 2024 เซิร์ฟเวอร์การดึงข้อมูลโฆษณาต้องทำงานในสภาพแวดล้อม Trusted Execution Environment (TEE) และจะแสดงอินเทอร์เฟซ GRPC/Proto บริษัทเทคโนโลยีโฆษณาต้องตั้งค่าเซิร์ฟเวอร์นี้และระบุ URL ของเซิร์ฟเวอร์ในฐานะส่วนหนึ่งของการทำให้สแต็ก B&A ใช้งานได้ การใช้งานบริการนี้ที่ทำงานใน TEE จะอยู่ใน Privacy Sandbox GitHub และในส่วนที่เหลือของเอกสารประกอบ เราจะถือว่านี่เป็นโค้ดที่ใช้ในการทำให้ใช้งานได้

ตั้งแต่เดือนเมษายน 2024 เป็นต้นไป เวอร์ชัน B&A จะรองรับการดึงข้อมูลเส้นทางตามบริบท ในกรณีนี้ เซิร์ฟเวอร์การเสนอราคาจะได้รับรายการตัวระบุโฆษณาที่ส่งโดยเซิร์ฟเวอร์ RTB ในระหว่างส่วนบริบทของการประมูล ระบบจะส่งตัวระบุไปยังเซิร์ฟเวอร์ TEE KV เพื่อดึงข้อมูลทั้งหมดที่เกี่ยวข้องกับโฆษณาที่จะใช้ในระหว่างขั้นตอนการเสนอราคา (เช่น URL ที่แสดงผลโฆษณา ข้อมูลเมตา และการฝังโฆษณาที่จะใช้ในการเลือกบนสุด) เส้นทางที่สองนี้ไม่จำเป็นต้องมีการใช้ตรรกะใดโดยเฉพาะ ดังนั้นเราจะบันทึกเฉพาะวิธีกำหนดค่ากรณีการใช้งานการดึงข้อมูลโฆษณาที่อิงตาม TEE เท่านั้น

UDF คำขอแฮนเดิล
function HandleRequest(requestMetadata, preparedDataForAdRetrieval,
                      deviceMetadata, contextualSignals) {
    return adsMetadataString;
}

โดยที่

  • requestMetadata: JSON ข้อมูลเมตาเซิร์ฟเวอร์ตามคำขอไปยัง UDF ตอนนี้ยังว่างอยู่
  • preparedDataForAdRetrieval: เนื้อหาของช่องนี้ขึ้นอยู่กับกลยุทธ์การดึงข้อมูลโฆษณา ในกรณีที่มีการดึงข้อมูลโฆษณาตามบริบท พารามิเตอร์นี้จะมีสัญญาณดิบที่มาจากอุปกรณ์และส่งจากบริการเสนอราคา ในกรณีที่มีการดึงข้อมูลโฆษณา TEE โดยใช้เซิร์ฟเวอร์การดึงข้อมูลโฆษณา พารามิเตอร์นี้จะประกอบด้วยผลลัพธ์ของ prepareDataForAdRetrieval UDF หมายเหตุ: ในขั้นตอนนี้ ระบบจะถอดรหัสและไม่เข้ารหัสสัญญาณของแอปที่ได้รับการคุ้มครอง
  • deviceMetadata: ออบเจ็กต์ JSON ที่มีข้อมูลเมตาของอุปกรณ์ที่ส่งต่อโดยบริการโฆษณาของผู้ขาย โปรดดูรายละเอียดเพิ่มเติมในเอกสารประกอบเกี่ยวกับ B&A
    • X-Accept-Language: ภาษาที่ใช้ในอุปกรณ์
    • X-User-Agent: User Agent ที่ใช้ในอุปกรณ์
    • X-BnA-Client-IP: ที่อยู่ IP ของอุปกรณ์
  • contextualSignals: สตริงที่กำหนดเองซึ่งมีต้นทางมาจากเซิร์ฟเวอร์การเสนอราคาตามบริบทที่ดำเนินการโดย DSP เดียวกัน เนื่องจากคาดว่า UDF จะถอดรหัสสตริงและใช้งานได้ สัญญาณบริบทอาจมีข้อมูลใดๆ เช่น ข้อมูลเวอร์ชันโมเดล ML สำหรับการฝังที่มีการปกป้องซึ่งส่งผ่าน สัญญาณของแอปที่มีการป้องกัน

UDF ควรแสดงผลสตริงเมื่อสําเร็จ ระบบจะส่งสตริงกลับไปยังเซิร์ฟเวอร์การเสนอราคาซึ่งจะส่งผ่านสตริงไปยัง UDF ของ generateBid แม้ว่าสตริงจะเป็นเพียงสตริงง่ายๆ ก็ได้ แต่ส่วนใหญ่แล้วสตริงควรเป็นออบเจ็กต์อนุกรมที่มีสคีมาที่กำหนดโดยเทคโนโลยีโฆษณาแต่ละรายการ ไม่มีข้อจำกัดในสคีมาตราบใดที่ตรรกะ generateBid ของเทคโนโลยีโฆษณาจดจำและใช้สตริงได้

ตั้งค่าระบบเพื่อการพัฒนา

Android

ในการตั้งค่าสภาพแวดล้อมในการพัฒนาซอฟต์แวร์ Android คุณจะต้องดำเนินการต่อไปนี้

  1. สร้างโปรแกรมจำลอง (แนะนำ) หรืออุปกรณ์จริงที่เรียกใช้อิมเมจตัวอย่างสำหรับนักพัฒนาซอฟต์แวร์ 10
  2. เรียกใช้โค้ดต่อไปนี้
adb shell am start -n com.google.android.adservices.api/com.android.adservices.ui.settings.activities.AdServicesSettingsMainActivity

จากนั้นเลือกตัวเลือกที่แสดงเพื่อให้ความยินยอมต่อโฆษณาที่แอปแนะนำ

  1. เรียกใช้คำสั่งต่อไปนี้เพื่อเปิดใช้ API ที่เกี่ยวข้อง คุณอาจต้องเรียกใช้ซ้ำอีกเป็นครั้งคราวเนื่องจากระบบจะซิงค์การกำหนดค่าเริ่มต้นของการปิดใช้เป็นระยะๆ
adb shell device_config put adservices fledge_custom_audience_service_kill_switch false;  adb shell device_config put adservices fledge_select_ads_kill_switch false; adb shell device_config put adservices fledge_on_device_auction_kill_switch false; adb shell device_config put adservices fledge_auction_server_kill_switch false; adb shell "device_config put adservices disable_fledge_enrollment_check true";  adb shell device_config put adservices ppapi_app_allow_list '\*'; adb shell device_config put adservices fledge_auction_server_overall_timeout_ms 60000;
  1. รีสตาร์ทอุปกรณ์
  2. ลบล้างคีย์การประมูลของอุปกรณ์เพื่อชี้ไปยังเซิร์ฟเวอร์คีย์การประมูล คุณต้องเรียกใช้ขั้นตอนนี้ก่อนที่จะเรียกใช้การประมูล เพื่อป้องกันไม่ให้ระบบแคชคีย์ที่ไม่ถูกต้อง

การเสนอราคาและบริการประมูล

หากต้องการตั้งค่าเซิร์ฟเวอร์ B&A โปรดดูเอกสารการตั้งค่าด้วยตนเอง

เอกสารนี้จะเน้นที่วิธีกำหนดค่าเซิร์ฟเวอร์สำหรับผู้ซื้อโดยเฉพาะ เนื่องจากผู้ขายไม่จำเป็นต้องทำการเปลี่ยนแปลง

ข้อกำหนดเบื้องต้น

ก่อนที่จะทำให้สแต็กบริการ B&A ใช้งานได้ เทคโนโลยีโฆษณาของผู้ซื้อต้องมีคุณสมบัติต่อไปนี้

  • ตรวจสอบว่าลูกค้าได้ติดตั้งใช้งานบริการดึงโฆษณา TEE ที่ตนเองมี (ดูส่วนที่เกี่ยวข้อง)
  • ตรวจสอบว่าเทคโนโลยีโฆษณามี UDF ที่จําเป็นทั้งหมด (prepareDataForAdRetrieval, generateBid, reportWin, HandleRequest) ที่กำหนดไว้และโฮสต์

ความเข้าใจเกี่ยวกับวิธีที่การประมูลที่มีการคุ้มครองซึ่งมี Protected Audience ทำงานร่วมกับ B&A ก็มีประโยชน์เช่นกัน แต่อาจไม่ใช่ข้อบังคับ

การกำหนดค่า Terraform

หากต้องการใช้สัญญาณแอปที่ได้รับการคุ้มครอง เทคโนโลยีโฆษณาต้องมีคุณสมบัติดังนี้

  • เปิดใช้การรองรับ Protected App Signals ใน B&A
  • ระบุปลายทางของ URL ที่ดึงข้อมูล UDF ใหม่สำหรับ prepareDataForAdRetrieval, generateBid และ reportWin ได้

นอกจากนี้ คู่มือนี้ยังมีสมมติฐานว่าเทคโนโลยีโฆษณาที่ต้องการใช้ B&A สําหรับรีมาร์เก็ตติ้งจะยังคงตั้งค่าแฟล็กการกําหนดค่าที่มีอยู่ทั้งหมดสําหรับการประมูลรีมาร์เก็ตติ้งตามปกติ

การกำหนดค่าเทคโนโลยีโฆษณาของผู้ซื้อ

ตัวอย่างของการใช้ไฟล์สาธิตนี้ ผู้ซื้อจะต้องตั้งค่าแฟล็กดังต่อไปนี้

  • เปิดใช้สัญญาณแอปที่มีการป้องกัน: เปิดใช้เพื่อรวบรวมข้อมูลสัญญาณแอปที่ได้รับการคุ้มครอง
  • URL ของสัญญาณแอปที่มีการป้องกัน: ตั้งค่าเป็น URL ของเซิร์ฟเวอร์สัญญาณแอปที่ได้รับการคุ้มครอง

เทคโนโลยีโฆษณาต้องแทนที่ URL ที่ถูกต้องในตัวยึดตำแหน่งสำหรับช่องต่อไปนี้

module "buyer" {
  # ... More config here.

  runtime_flags = {
    # ... More config here.

    ENABLE_PROTECTED_APP_SIGNALS                  = "true"
    PROTECTED_APP_SIGNALS_GENERATE_BID_TIMEOUT_MS = "60000"
    TEE_AD_RETRIEVAL_KV_SERVER_ADDR               = "<service mesh address of the instance>"
    AD_RETRIEVAL_TIMEOUT_MS                       = "60000"
    BUYER_CODE_FETCH_CONFIG                       = <<EOF
    {
        "protectedAppSignalsBiddingJsUrl": "<URL to Protected App Signals generateBid UDF>",
        "urlFetchTimeoutMs": 60001, # This has to be > 1 minute.
        "urlFetchPeriodMs": 13000000,
        "prepareDataForAdsRetrievalJsUrl": "<URL to the UDF>"
    }
    EOF

  }  # runtime_flags

}  # Module "buyer"

การกำหนดค่าเทคโนโลยีโฆษณาของผู้ขาย

ตัวอย่างเช่น หากใช้ไฟล์สาธิตนี้ ผู้ขายจะต้องตั้งค่าแฟล็กต่อไปนี้ (หมายเหตุ: ไฮไลต์เฉพาะการกําหนดค่าที่เกี่ยวข้องกับสัญญาณแอปที่ได้รับการคุ้มครองเท่านั้น) เทคโนโลยีโฆษณาต้องตรวจสอบว่าเทคโนโลยีเหล่านั้นแทนที่ URL ที่ถูกต้องในตัวยึดตำแหน่ง ดังนี้

module "seller" {
  # ... More config here.

  runtime_flags = {
    # ... More config here.

    ENABLE_PROTECTED_APP_SIGNALS                  = "true"

    SELLER_CODE_FETCH_CONFIG                           = <<EOF
  {
    "urlFetchTimeoutMs": 60001, # This has to be > 1 minute.
    "urlFetchPeriodMs": 13000000,
    "protectedAppSignalsBuyerReportWinJsUrls": {"<Buyer Domain>": "URL to reportWin UDF"}
  }
  EOF

  }  # runtime_flags

}  # Module "seller"

บริการ KV และการดึงข้อมูลโฆษณา

ระบบจะกำหนดให้มีการติดตั้งใช้งานบริการ KV 1 หรือ 2 อินสแตนซ์ โดยขึ้นอยู่กับกลยุทธ์ที่เลือกเพื่อรองรับการดึงข้อมูล เราจะเรียกอินสแตนซ์ KV ที่ใช้สําหรับการดึงข้อมูลโฆษณาที่อิงตาม TEE เป็น Ad Retrieval Server และอ้างอิงอินสแตนซ์เพื่อรองรับการดึงข้อมูลตามเส้นทางตามบริบทเป็น KV Lookup Server

ในทั้ง 2 กรณี การทำให้เซิร์ฟเวอร์ใช้งานได้จะเป็นไปตามเอกสารประกอบในGitHub เซิร์ฟเวอร์ KV ความแตกต่างระหว่าง 2 กรณีคือกรณีการค้นหาจะทำงานนอกกล่องโดยไม่มีการกำหนดค่าเพิ่มเติม ในขณะที่การดึงข้อมูลจำเป็นต้องมีการติดตั้งใช้งาน HandleRequest UDF เพื่อติดตั้งใช้งานตรรกะการดึงข้อมูล ดูรายละเอียดเพิ่มเติมได้ในคู่มือการเริ่มต้นใช้งานเซิร์ฟเวอร์ KV โปรดทราบว่า B&A คาดหวังให้ทั้งสองบริการใช้งานได้ในโครงข่ายบริการเดียวกันกับบริการเสนอราคา

ตัวอย่างการตั้งค่า

ลองพิจารณาสถานการณ์ต่อไปนี้: เทคโนโลยีโฆษณาจะจัดเก็บสัญญาณที่เกี่ยวข้องตามการใช้งานแอปของผู้ใช้โดยใช้ Protected App Signals API ในตัวอย่างของเรา ระบบจะจัดเก็บสัญญาณซึ่งแสดงถึงการซื้อในแอปจากหลายๆ แอป ในระหว่างการประมูล ระบบจะรวบรวมและส่งสัญญาณที่เข้ารหัสไปยังการประมูลที่มีการป้องกันซึ่งทำงานในส่วน B&A UDF ของผู้ซื้อที่ทํางานอยู่ใน B&A จะใช้สัญญาณเพื่อดึงผู้สมัครโฆษณาและคำนวณราคาเสนอ

[ผู้ซื้อ] ตัวอย่างสัญญาณ

เพิ่มสัญญาณที่มีคีย์ 0 และค่า 1

{
  "put": {
    "AA==": "AQ=="
  },
  "update_encoder": {
    "action": "REGISTER",
    "endpoint": "https://example.com/example_script"
  }
}

เพิ่มสัญญาณที่มีคีย์ 1 และค่า 2

{
  "put": {
    "AQ==": "Ag=="
  },
  "update_encoder": {
    "action": "REGISTER",
    "endpoint": "https://example.com/example_script"
  }
}

ตัวอย่างสัญญาณการเข้ารหัสของ [Buyer]

เข้ารหัสแต่ละสัญญาณเป็น 2 ไบต์ โดยไบต์แรกเป็นไบต์แรกของคีย์สัญญาณและไบต์ที่ 2 เป็นไบต์แรกของค่าสัญญาณ

function encodeSignals(signals, maxSize) {
  // if there are no signals don't write a payload
  if (signals.size === 0) {
      return {};
  }

  let result = new Uint8Array(signals.size * 2);
  let index = 0;
  
  for (const [key, values] of signals.entries()) {
    result[index++] = key[0];
    result[index++] = values[0].signal_value[0];
  }
  
  return { 'status': 0, 'results': result};
}

[Buyer] ตัวอย่างPrepareDataForAdRetrieval

/**
 * `encodedOnDeviceSignals` is a Uint8Array and would contain
 * the app signals emanating from device. For purpose of the
 * demo, in our sample example, we assume that device is sending
 * the signals with pair of bytes formatted as following:
 * "<id><In app spending>". Where id corresponds to an ad category
 * that user uses on device, and the in app spending is a measure
 * of how much money the user has spent in this app category
 * previously. In our example, id of 0 will correspond to a
 * fitness ad category and a non-zero id will correspond to
 * food app category -- though this info will be useful
 * later in the B&A pipeline.
 *
 * Returns a JSON object indicating what type of ad(s) may be
 * most relevant to the user. In a real setup ad techs might
 * want to decode the signals as part of this script.
 *
 * Note: This example script makes use of only encoded device signals
 * but adtech can take other signals into account as well to prepare
 * the data that will be useful down stream for ad retrieval and
 * bid generation. The max length of the app signals used in this
 * sample example is arbitrarily limited to 4 bytes.
 */
function prepareDataForAdRetrieval(encodedOnDeviceSignals,
                                   encodedOnDeviceSignalsVersion,
                                   sellerAuctionSignals,
                                   contextualSignals) {
  if (encodedOnDeviceSignals.length === 0 || encodedOnDeviceSignals.length > 4 ||
      encodedOnDeviceSignals.length % 2 !== 0) {
     throw "Expected encoded signals length to be an even number in (0, 4]";
  }

  var preparedDataForAdRetrieval = {};
  for (var i = 0; i < encodedOnDeviceSignals.length; i += 2) {
    preparedDataForAdRetrieval[encodedOnDeviceSignals[i]] = encodedOnDeviceSignals[i + 1];
  }
  return preparedDataForAdRetrieval;
}

[ผู้ซื้อ] UDF การดึงข้อมูลโฆษณาตัวอย่าง

ในตัวอย่างของเรา เซิร์ฟเวอร์การดึงข้อมูลโฆษณาจะส่งข้อมูลเมตา (ซึ่งก็คือรหัสของโฆษณาแต่ละรายการในตัวอย่างนี้ แต่อาจมีข้อมูลอื่นๆ สำหรับแต่ละโฆษณาที่มีประโยชน์ต่อการสร้างราคาเสนอในภายหลัง) สำหรับตัวเลือกโฆษณายอดนิยมแต่ละรายการ

function HandleRequest(requestMetadata, protectedSignals, deviceMetadata,
                      contextualSignals) {
 return "[{\"adId\":\"0\"},{\"adId\":\"1\"}]"

[ผู้ซื้อ] ตัวอย่าง generateBid

/**
 * This script receives the data returned by the ad retrieval service
 * in the `ads` argument. This argument is supposed to contain all
 * the Protected App Signals related ads and the metadata obtained from the retrieval
 * service.
 *
 * `preparedDataForAdRetrieval` argument contains the data returned
 * from the `prepareDataForAdRetrieval` UDF.
 *
 * This script is responsible for generating bids for the ads
 * collected from the retrieval service and ad techs can decide to
 * run a small inference model as part of this script in order to
 * decide the best bid given all the signals available to them.
 *
 * For the purpose of the demo, this sample script assumes
 * that ad retrieval service has sent us most relevant ads for the
 * user and this scripts decides on the ad render URL as well as
 * what value to bid for each ad based on the previously decoded
 * device signals. For simplicity sake, this script only considers
 * 2 types of app categories i.e. fitness and food.
 *
 * Note: Only one bid is returned among all the
 * input ad candidates.
 */
function generateBid(ads, sellerAuctionSignals, buyerSignals, preparedDataForAdRetrieval) {
  if (ads === null) {
    console.log("No ads obtained from the ad retrieval service")
    return {};
  }     
        
  const kFitnessAd = "0";
  const kFoodAd = "1";
  const kBuyerDomain = "https://buyer-domain.com";
        
  let resultingBid = 0;
  let resultingRender = kBuyerDomain + "/no-ad";
  for (let i = 0 ; i < ads.length; ++i) {
    let render = "";
    let bid = 0;
    switch (ads[i].adId) {
      case kFitnessAd:
        render = kBuyerDomain + "/get-fitness-app";
        bid = preparedDataForAdRetrieval[kFitnessAd];
        break;
      case kFoodAd:
        render = kBuyerDomain + "/get-fastfood-app";
        bid = preparedDataForAdRetrieval[kFoodAd];
        break;
      default:
        console.log("Unknown ad category");
        render = kBuyerDomain + "/no-ad";
        break;
    }
    console.log("Existing bid: " + resultingBid + ", incoming candidate bid: " + bid);
    if (bid > resultingBid) {
      resultingBid = bid;
      resultingRender = render;
    }
  }
  return {"render": resultingRender, "bid": resultingBid};
}

[ผู้ซื้อ] ตัวอย่าง reportWin

UDF ของ reportWin รายงานต่อผู้ซื้อว่าชนะการประมูล

function reportWin(auctionSignals, perBuyerSignals, signalsForWinner,
                                       buyerReportingSignals, directFromSellerSignals,
                                       egressPayload,
                                       temporaryUnlimitedEgressPayload) {
  sendReportTo("https://buyer-controlled-domain.com/");
  registerAdBeacon({"clickEvent":"https://buyer-controlled-domain.com/clickEvent"});
  return;
}

[ผู้ขาย] การตั้งค่าเซิร์ฟเวอร์ KV

ผู้ขายต้องตั้งค่าเซิร์ฟเวอร์ KV ของสัญญาณการให้คะแนนเพื่อให้สามารถแมปจาก URL การแสดงโฆษณากับสัญญาณการให้คะแนนที่เกี่ยวข้อง ตัวอย่างเช่น หากผู้ซื้อส่งคืน https:/buyer-domain.com/get-fitness-app และ https:/buyer-domain.com/get-fastfood-app ผู้ขายสามารถมีการตอบสนองของสัญญาณการให้คะแนนต่อไปนี้เมื่อ SFE สอบถามโดยใช้ GET บน https://key-value-server-endpoint.com?client_type=1&renderUrls=<render-url-returned-by-the-buyer>

{
   "renderUrls" : {
      "https:/buyer-domain.com/get-fitness-app" : [
         "1",
         "2"
      ],
      "https:/buyer-domain.com/get-fastfood-app" : [
         "3",
         "4"
      ]
   }
}

[Seller] ตัวอย่าง scoreAd

/**
 * This module generates a random desirability score for the Protected App
 * Signals ad in this example. In a production deployment,
 * however, the sellers would want to use all the available signals to generate
 * a score for the ad.
 */
function getRandomInt(max) {
  return Math.floor(Math.random() * max);
}

function scoreAd(adMetadata, bid, auctionConfig,
                                   trustedScoringSignals, deviceSignals,
                                   directFromSellerSignals) {
  return {
    "desirability": getRandomInt(10000),
    "allowComponentAuction": false
  };
}

[Seller] ตัวอย่าง report Results

function reportResult(auctionConfig, sellerReportingSignals, directFromSellerSignals){
  let signalsForWinner = {};
    sendReportTo("https://seller-controlled-domain.com");
    registerAdBeacon({"clickEvent":
                    "https://seller-controlled-domain.com/clickEvent"});
    return signalsForWinner;
}

แอปตัวอย่าง

เพื่อเป็นตัวอย่างวิธีการใช้ API ในการสร้างแอปที่ใช้ขั้นตอนแบบง่ายๆ ตามที่อธิบายไว้ข้างต้น เราได้สร้างแอปตัวอย่างจาก Protected App Signals ซึ่งดูได้ในที่เก็บตัวอย่างนี้