上傳轉換

本指南提供詳細操作說明,協助您使用 Campaign Manager 360 API Conversions 服務上傳離線轉換資料。繼續操作前,建議您先參閱總覽,瞭解離線轉換的簡介,並熟悉本指南中討論的概念。

設定轉換資源

轉換上傳程序的第一步,是建立一或多個 Conversion 資源物件。每個物件都代表單一轉換事件,並包含幾個必填欄位:

欄位 說明
floodlightActivityId 要與這項轉換建立關聯的 Floodlight 活動。
floodlightConfigurationId 指定活動使用的 Floodlight 設定。
ordinal 這個值用於控管如何簡化同一天來自相同裝置或使用者的轉換。詳情請參閱常見問題
timestampMicros 轉換的時間戳記,以 Unix 紀元後的時間表示,以微秒為單位。

此外,每個物件都必須包含下列其中一個欄位:

欄位 說明
encryptedUserId %m 比對巨集資料移轉取得的單一加密使用者 ID。
encryptedUserIdCandidates[] %m 比對巨集資料移轉取得的加密使用者 ID 清單。系統會使用在指定 timestampMicros 前記錄到 Floodlight 曝光的第一個 ID。如果沒有任何 ID 與現有曝光相符,系統會擲回錯誤。
dclid Campaign Manager 360 或 Display & Video 360 產生的多媒體廣告點擊 ID
gclid Google Ads 或 Search Ads 360 產生的 Google 點擊 ID
matchId 由廣告主建立的專屬 ID,透過 Floodlight 代碼傳遞到 Campaign Manager 360。
mobileDeviceId 採用廣告識別碼或廣告 ID 格式的反向解碼行動裝置 ID,或是支援的連網電視裝置平台 (Roku、Fire TV、Android TV、Apple TV、Xbox、Samsung、Vizio) 提供的連網電視廣告 ID (IFA)。請注意,Google 不支援 YouTube 連網電視 IFA。

最後,每筆轉換都有兩項指標:

欄位 說明
quantity 必填。與轉換相關聯的項目數量。如要計入特定指標 (例如轉換總數),數量至少要為 1。
value 與轉換相關聯的金額。以擁有 Floodlight 設定的廣告主所用幣別解讀。

選用欄位請參閱參考說明文件

下例說明如何建立簡單的轉換資源物件:

C#

// Generate a timestamp in milliseconds since Unix epoch.
TimeSpan timeSpan = DateTime.UtcNow - new DateTime(1970, 1, 1);
long currentTimeInMilliseconds = (long) timeSpan.TotalMilliseconds;

// Find the Floodlight configuration ID based on the provided activity ID.
FloodlightActivity floodlightActivity =
    service.FloodlightActivities.Get(profileId, floodlightActivityId).Execute();
long floodlightConfigurationId = (long) floodlightActivity.FloodlightConfigurationId;

// Create the conversion.
Conversion conversion = new Conversion();
conversion.EncryptedUserId = conversionUserId;
conversion.FloodlightActivityId = floodlightActivityId;
conversion.FloodlightConfigurationId = floodlightConfigurationId;
conversion.Ordinal = currentTimeInMilliseconds.ToString();
conversion.TimestampMicros = currentTimeInMilliseconds * 1000;

Java

long currentTimeInMilliseconds = System.currentTimeMillis();

// Find Floodlight configuration ID based on the provided activity ID.
FloodlightActivity floodlightActivity = reporting.floodlightActivities()
    .get(profileId, floodlightActivityId).execute();
long floodlightConfigurationId = floodlightActivity.getFloodlightConfigurationId();

Conversion conversion = new Conversion();
conversion.setEncryptedUserId(encryptedUserId);
conversion.setFloodlightActivityId(floodlightActivityId);
conversion.setFloodlightConfigurationId(floodlightConfigurationId);
conversion.setOrdinal(String.valueOf(currentTimeInMilliseconds));
conversion.setTimestampMicros(currentTimeInMilliseconds * 1000);

PHP

$currentTimeInMicros = time() * 1000 * 1000;

// Find Floodlight configuration ID based on provided activity ID.
$activity = $this->service->floodlightActivities->get(
    $values['user_profile_id'],
    $values['floodlight_activity_id']
);
$floodlightConfigId = $activity->getFloodlightConfigurationId();

$conversion = new Google_Service_Dfareporting_Conversion();
$conversion->setEncryptedUserId($values['encrypted_user_id']);
$conversion->setFloodlightActivityId($values['floodlight_activity_id']);
$conversion->setFloodlightConfigurationId($floodlightConfigId);
$conversion->setOrdinal($currentTimeInMicros);
$conversion->setTimestampMicros($currentTimeInMicros);

Python

# Look up the Floodlight configuration ID based on activity ID.
floodlight_activity = service.floodlightActivities().get(
    profileId=profile_id, id=floodlight_activity_id).execute()
floodlight_config_id = floodlight_activity['floodlightConfigurationId']

current_time_in_micros = int(time.time() * 1000000)

# Construct the conversion.
conversion = {
    'encryptedUserId': encrypted_user_id,
    'floodlightActivityId': floodlight_activity_id,
    'floodlightConfigurationId': floodlight_config_id,
    'ordinal': current_time_in_micros,
    'timestampMicros': current_time_in_micros
}

Ruby

# Look up the Floodlight configuration ID based on activity ID.
floodlight_activity = service.get_floodlight_activity(profile_id,
  floodlight_activity_id)
floodlight_config_id = floodlight_activity.floodlight_configuration_id

current_time_in_micros = DateTime.now.strftime('%Q').to_i * 1000

# Construct the conversion.
conversion = DfareportingUtils::API_NAMESPACE::Conversion.new(
  encrypted_user_id: encrypted_user_id,
  floodlight_activity_id: floodlight_activity_id,
  floodlight_configuration_id: floodlight_config_id,
  ordinal: current_time_in_micros,
  timestamp_micros: current_time_in_micros
)

指定加密資訊

如要將離線轉換歸因於加密使用者 ID (如上例所示),您需要在插入要求中提供加密方式的詳細資料。具體來說,您需要瞭解:

  1. 加密來源:說明一批加密 ID 的來源。可接受的值為 AD_SERVING (來自 %m 比對巨集的 ID) 或 DATA_TRANSFER (來自資料移轉檔案的 ID)。

  2. 加密實體:用於加密使用者 ID 的一組專屬值。如果來源是資料轉移,這些值通常與 Campaign Manager 360 帳戶相關;如果來源是 %m 巨集,這些值通常與 Campaign Manager 360 廣告主相關,但並非一律如此。如有疑問,請洽詢 Campaign Manager 360 帳戶代表或 Campaign Manager 360 支援團隊

如有需要,請建立 EncryptionInfo 物件來指定這些值,這是轉換上傳程序的第二個步驟:

C#

// Create the encryption info.
EncryptionInfo encryptionInfo = new EncryptionInfo();
encryptionInfo.EncryptionEntityId = encryptionEntityId;
encryptionInfo.EncryptionEntityType = encryptionEntityType;
encryptionInfo.EncryptionSource = encryptionSource;

Java

// Create the encryption info.
EncryptionInfo encryptionInfo = new EncryptionInfo();
encryptionInfo.setEncryptionEntityId(encryptionEntityId);
encryptionInfo.setEncryptionEntityType(encryptionEntityType);
encryptionInfo.setEncryptionSource(encryptionSource);

PHP

$encryptionInfo = new Google_Service_Dfareporting_EncryptionInfo();
$encryptionInfo->setEncryptionEntityId($values['encryption_entity_id']);
$encryptionInfo->setEncryptionEntityType($values['encryption_entity_type']);
$encryptionInfo->setEncryptionSource($values['encryption_source']);

Python

# Construct the encryption info.
encryption_info = {
    'encryptionEntityId': encryption_entity_id,
    'encryptionEntityType': encryption_entity_type,
    'encryptionSource': encryption_source
}

Ruby

# Construct the encryption info.
encryption_info = DfareportingUtils::API_NAMESPACE::EncryptionInfo.new(
  encryption_entity_id: encryption[:entity_id],
  encryption_entity_type: encryption[:entity_type],
  encryption_source: encryption[:source]
)

請注意,每個插入要求只能包含一個 EncryptionInfo 物件。也就是說,特定要求中包含的所有轉換都必須來自相同來源,並使用相同的加密實體。

產生插入要求

這項程序的最後一個步驟是透過呼叫 batchinsert 上傳轉換。這個方法會接受 ConversionsBatchInsertRequest 物件,其中包含要上傳的一組轉換,以及相關聯的加密資訊 (如有必要):

C#

// Insert the conversion.
ConversionsBatchInsertRequest request = new ConversionsBatchInsertRequest();
request.Conversions = new List<Conversion>() { conversion };
request.EncryptionInfo = encryptionInfo;

ConversionsBatchInsertResponse response =
    service.Conversions.Batchinsert(request, profileId).Execute();

Java

ConversionsBatchInsertRequest request = new ConversionsBatchInsertRequest();
request.setConversions(ImmutableList.of(conversion));
request.setEncryptionInfo(encryptionInfo);

ConversionsBatchInsertResponse response = reporting.conversions()
    .batchinsert(profileId, request).execute();

PHP

$batch = new Google_Service_Dfareporting_ConversionsBatchInsertRequest();
$batch->setConversions([$conversion]);
$batch->setEncryptionInfo($encryptionInfo);

$result = $this->service->conversions->batchinsert(
    $values['user_profile_id'],
    $batch
);

Python

# Insert the conversion.
request_body = {
    'conversions': [conversion],
    'encryptionInfo': encryption_info
}
request = service.conversions().batchinsert(profileId=profile_id,
                                            body=request_body)
response = request.execute()

Ruby

# Construct the batch insert request.
batch_insert_request =
  DfareportingUtils::API_NAMESPACE::ConversionsBatchInsertRequest.new(
    conversions: [conversion],
    encryption_info: encryption_info
  )

# Insert the conversion.
result = service.batchinsert_conversion(profile_id, batch_insert_request)

請注意,Campaign Manager 360 會盡可能在要求中插入每項轉換,而不是將整個批次視為全有或全無的交易。如果批次中的部分轉換無法插入,其他轉換可能仍會成功插入。因此,建議您檢查傳回的 ConversionsBatchInsertResponse,判斷每項轉換的狀態:

C#

// Handle the batchinsert response.
if (!response.HasFailures.Value) {
  Console.WriteLine("Successfully inserted conversion for encrypted user ID {0}.",
      conversionUserId);
} else {
  Console.WriteLine("Error(s) inserting conversion for encrypted user ID {0}:",
      conversionUserId);

  ConversionStatus status = response.Status[0];
  foreach(ConversionError error in status.Errors) {
    Console.WriteLine("\t[{0}]: {1}", error.Code, error.Message);
  }
}

Java

if (!response.getHasFailures()) {
  System.out.printf("Successfully inserted conversion for encrypted user ID %s.%n",
      encryptedUserId);
} else {
  System.out.printf("Error(s) inserting conversion for encrypted user ID %s:%n",
      encryptedUserId);

  // Retrieve the conversion status and report any errors found. If multiple conversions
  // were included in the original request, the response would contain a status for each.
  ConversionStatus status = response.getStatus().get(0);
  for (ConversionError error : status.getErrors()) {
    System.out.printf("\t[%s]: %s.%n", error.getCode(), error.getMessage());
  }
}

PHP

if (!$result->getHasFailures()) {
    printf(
        'Successfully inserted conversion for encrypted user ID %s.',
        $values['encrypted_user_id']
    );
} else {
    printf(
        'Error(s) inserting conversion for encrypted user ID %s:<br><br>',
        $values['encrypted_user_id']
    );

    $status = $result->getStatus()[0];
    foreach ($status->getErrors() as $error) {
        printf('[%s] %s<br>', $error->getCode(), $error->getMessage());
    }
}

Python

if not response['hasFailures']:
  print ('Successfully inserted conversion for encrypted user ID %s.'
         % encrypted_user_id)
else:
  print ('Error(s) inserting conversion for encrypted user ID %s.'
         % encrypted_user_id)

  status = response['status'][0]
  for error in status['errors']:
    print '\t[%s]: %s' % (error['code'], error['message'])

Ruby

if result.has_failures
  puts format('Error(s) inserting conversion for encrypted user ID %s.',
    encrypted_user_id)

  status = result.status[0]
  status.errors.each do |error|
    puts format("\t[%s]: %s", error.code, error.message)
  end
else
  puts format('Successfully inserted conversion for encrypted user ID %s.',
    encrypted_user_id)
end

如上所示,回應的 status 欄位會包含原始要求中每個轉換的 ConversionStatus 物件。如果您只對插入失敗的轉換感興趣,可以使用 hasFailures 欄位快速判斷所提供批次中任何轉換是否失敗。

確認系統已處理轉換

上傳的轉換資料通常會在 24 小時內處理完畢,並顯示在報表中。如要確認上傳的轉換是否已處理,建議您執行 Floodlight 曝光報表。與其他歸因報表不同,這些報表預設會傳回歸因 (與廣告相關聯) 和未歸因的轉換。因此非常適合快速檢查您傳送的轉換資料是否已送達 Campaign Manager 360。