上傳轉換

本指南將詳細說明如何使用 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 產生的 Display Click ID
gclid Google Ads 或 Search Ads 360 產生的 Google 點擊 ID
matchId 由廣告主建立的不重複 ID,透過 Floodlight 代碼傳遞至 Campaign Manager 360。
mobileDeviceId IDFA 或 AdID 格式的未加密行動 ID,或是支援的連網電視裝置平台 (Roku、Fire TV、Android TV、Apple TV、Xbox、Samsung、Vizio) 的連網電視廣告 ID (IFA)。請注意,Google 不支援 YouTube 連網電視 IFA。

選用欄位會在參考說明文件中說明。請注意,雖然數量欄位為選用欄位,但在執行報表時,轉換次數必須至少為 1,才能計入特定指標 (例如總轉換次數)。

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

C#JavaPHPPython小茹
// 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;
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);
$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);
# 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
}
# 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 (如上一個範例所示),就必須在插入要求中提供相關詳細資料,說明如何加密這些 ID。具體來說,您需要瞭解以下事項:

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

  2. 加密實體:這是用來加密使用者 ID 的專屬值組合。當來源為資料移轉時,這些值通常會與 Campaign Manager 360 帳戶相關聯;當來源為 %m 巨集時,則會與 Campaign Manager 360 廣告主相關聯,但不一定是這樣。如果不確定,請洽詢 Campaign Manager 360 帳戶代表或 Campaign Manager 360 支援團隊,進一步瞭解詳情。

在必要時,請建立 EncryptionInfo 物件,指定這些值,這是轉換上傳程序的第二個步驟:

C#JavaPHPPython小茹
// Create the encryption info.
EncryptionInfo encryptionInfo = new EncryptionInfo();
encryptionInfo
.EncryptionEntityId = encryptionEntityId;
encryptionInfo
.EncryptionEntityType = encryptionEntityType;
encryptionInfo
.EncryptionSource = encryptionSource;
// Create the encryption info.
EncryptionInfo encryptionInfo = new EncryptionInfo();
encryptionInfo
.setEncryptionEntityId(encryptionEntityId);
encryptionInfo
.setEncryptionEntityType(encryptionEntityType);
encryptionInfo
.setEncryptionSource(encryptionSource);
$encryptionInfo = new Google_Service_Dfareporting_EncryptionInfo();
$encryptionInfo
->setEncryptionEntityId($values['encryption_entity_id']);
$encryptionInfo
->setEncryptionEntityType($values['encryption_entity_type']);
$encryptionInfo
->setEncryptionSource($values['encryption_source']);
# Construct the encryption info.
encryption_info
= {
   
'encryptionEntityId': encryption_entity_id,
   
'encryptionEntityType': encryption_entity_type,
   
'encryptionSource': encryption_source
}
# 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#JavaPHPPython小茹
// Insert the conversion.
ConversionsBatchInsertRequest request = new ConversionsBatchInsertRequest();
request
.Conversions = new List<Conversion>() { conversion };
request
.EncryptionInfo = encryptionInfo;

ConversionsBatchInsertResponse response =
    service
.Conversions.Batchinsert(request, profileId).Execute();
ConversionsBatchInsertRequest request = new ConversionsBatchInsertRequest();
request
.setConversions(ImmutableList.of(conversion));
request
.setEncryptionInfo(encryptionInfo);

ConversionsBatchInsertResponse response = reporting.conversions()
   
.batchinsert(profileId, request).execute();
$batch = new Google_Service_Dfareporting_ConversionsBatchInsertRequest();
$batch
->setConversions([$conversion]);
$batch
->setEncryptionInfo($encryptionInfo);

$result
= $this->service->conversions->batchinsert(
    $values
['user_profile_id'],
    $batch
);
# Insert the conversion.
request_body
= {
   
'conversions': [conversion],
   
'encryptionInfo': encryption_info
}
request
= service.conversions().batchinsert(profileId=profile_id,
                                            body
=request_body)
response
= request.execute()
# 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#JavaPHPPython小茹
// 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);
 
}
}
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());
 
}
}
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());
   
}
}
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'])
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,這項功能就非常實用。