Downloading Campaigns from the Bing Ads API

in Bing Ads API

This article explains how to download your Bing Ads campaigns, ad groups, keywords, and ads using the Bing Ads API Bulk Service. You can also extract this data from the Campaign Management Service, but it's much slower for retrieving more than a few items, so you'll want to use the newer Bulk Service most of the time.

The Bing Ads API Bulk Download Service

The Bulk Download service allows you to download an entire account in a single CSV file. The file is the same as the one used by the Bing Ads Desktop tool: each row contains a single entity (campaign, ad group, keyword, ad, or target) and each column contains the fields for the entity. You can find out more about the structure of the file in the Bulk Service Schema.

The Bulk Download Service works asynchronously, so to download an account you request an extract file for an account, poll the service periodically until the file is ready, and then download the file from a temporary URL provided by the API. You can then process the file and import the campaign data into your system or perform other operations. The next three sections will describe each step in detail.

Requesting a Bulk Download File

You submit a download request using the DownloadCampaignsByAccountIds API operation with the following parameters:

  • AccountIds: The id of the account you want to download. Although the parameter takes an array of ids, you can only supply one per request.
  • DownloadFileType: The format of CSV file; either CSV or TSV.
  • Entities: The campaign items to export from Bing. You can find the available items in the Bulk Download Entity reference.
  • LastSyncTimeInUTC: The last time you updated your system. The API will only return entities created or modified after this date. You can request everything by omitting this parameter.

Given this, you can create a download request using the following code:

$accountId = "YOUR_ACCOUNT_ID";
 
$downloadRequest = array(
    "AccountIds" => array(new \SoapVar($accountId, XSD_LONG, 'xsd:long')),
    "DownloadFileType" => "Tsv",
    "Entities" => "Campaigns AdGroups Ads Keywords"
);
A Bulk Download Request

This code creates a request array using a supplied $accountId variable encoded into a SOAP long array. I've chosen a tab separated file type, as it's a bit easier to parse, and the minimum required entities. To add the last update date, add a date variable and format it using as an ISO 8601 date:

$lastSyncDate = strtotime("-7 days");
if ($lastSyncDate !== null) {
    $downloadRequest["LastSyncTimeInUTC"] = date("c", $lastSyncDate);
}
Adding the Optional Last Sync Date

Now that we've constructed a request, it can be sent to the API:

$response = $client->DownloadCampaignsByAccountIds($downloadRequest);
$requestId = $response->DownloadRequestId;
Calling the API Operation

This code calls the DownloadCampaignsByAccountIds operation and extracts the resulting request id that we need for the next part of the process. The code is using a standard PHP SOAP client that we need to initialize using Bing Ads API authentication headers and the bulk service location:

define("API_SERVER", "https://api.sandbox.bingads.microsoft.com");
define("BULK_API_ENDPOINT", API_SERVER .
        "/Api/Advertiser/CampaignManagement/v9/BulkService.svc?wsdl");
define("API_NAMESPACE", "https://bingads.microsoft.com/CampaignManagement/v9");
 
$client = new \SoapClient(BULK_API_ENDPOINT);
 
define("DEVELOPER_TOKEN", "BBD37VB98");
$username = "YOUR_USERNAME";
$password = "YOUR_PASSWORD";
$accountId = "YOUR_ACCOUNT_ID";
 
$headers = array();
$headers[] = new \SoapHeader(API_NAMESPACE, "UserName", $username);
$headers[] = new \SoapHeader(API_NAMESPACE, "Password", $password);
$headers[] = new \SoapHeader(API_NAMESPACE, "DeveloperToken", DEVELOPER_TOKEN);
$headers[] = new \SoapHeader(API_NAMESPACE, "CustomerAccountId", $accountId);
$client->__setSoapHeaders($headers);
A Bing Ads API Bulk Service Client

This code uses the API_SERVER constant to define the API server, which is either https://api.sandbox.bingads.microsoft.com for the sandbox or https://api.bingads.microsoft.com in production, then defines the API endpoint and namespace constants and creates a new SOAP Client. Next it sets a DEVELOPER_TOKEN constant, which is always BBD37VB98 in the sandbox and your own in production, then sets the required SOAP headers. You can use this client for all subsequent requests to the API for the given $username, $password, and $accountId.

Polling the Status of the Bulk Extract

Now that we've submitted a bulk download request, we need to poll the API using the GetDownloadStatus operation until the file is ready. This operation takes the $requesrId retrieved from the DownloadCampaignsByAccountIds operation, and returns a RequestStatus and DownloadUrl. The RequestStatus indicates the processing status, which is InProgress until the request completes or fails, and the DownloadUrl indicates the location of the completed extract file ready for download. The following code polls the API until the extract is ready for download:

$statusRequest = array(
    "DownloadRequestId" => $requestId
);
 
for ($pollDelay = 60, $status = "InProgress"; $status === "InProgress"; $pollDelay *= 1.5) {
    sleep($pollDelay);
    $response = $client->GetDownloadStatus($statusRequest);
    $status = $response->RequestStatus;
}
Waiting for the Bulk Request Completion

This script loops while the $status variable contains the status InProgress; it pauses for the number of seconds in $pollDelay, calls the GetDownloadStatus operation using the $requestId, and then extracts the resulting RequestStatus. Larger accounts take longer to process than smaller ones, so the script backs off from polling the API by increasing the $pollDelay variable each time around the loop to reduce the number of API calls it makes.

Once the extract has finished, the script can retrieve the location of the file:

$downloadUrl = $response->DownloadUrl;
Retrieving the Download URL

Downloading the Report

Now that you've got a URL, you can use it to download your extract file using cURL:

$zipFilename = "/tmp/bulk_download.zip";
 
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $downloadUrl);
curl_setopt($curl, CURLOPT_HEADER, false);
curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_SSLVERSION, 3);
 
$file = curl_exec($curl);
curl_close($curl);
file_put_contents($zipFilename, $file);
Download a Bing Bulk Extract File

Note that the Bing Ads API uses version 3 of SSL spec, and I've found that I had to set it explicitly as a cURL option.

The extract file is zipped up, so you need to unzip it before processing the entities and importing them into your system:

$zip = new \ZipArchive();
$zip->open($zipFilename);
 
// Process the rows in the file
$rows = explode("\n", trim($zip->getFromIndex(0)));
$headerRow = array_shift($rows);
 
foreach ($rows as $row) {
    $row = explode("\t", $row);
    print "Extracted {$row[0]} with an ID of '{$row[2]}'\n";
}
 
$zip->close();
Unzipping and Processing the File

Example Bing Bulk Download Script

Here's a full script containing the steps outlined in this tutorial:

<?php
 
// Your Bing Ads API developer token (set to 'BBD37VB98' for the sandbox)
define("DEVELOPER_TOKEN", "BBD37VB98");
 
// The Bing Ads API server; remove the 'sandbox' element for the live server
define("API_SERVER", "https://api.sandbox.bingads.microsoft.com");
 
// The Bulk Service location
define("BULK_API_ENDPOINT", API_SERVER .
        "/Api/Advertiser/CampaignManagement/v9/BulkService.svc?wsdl");
 
// The namespace of the Bulk Service
define("API_NAMESPACE", "https://bingads.microsoft.com/CampaignManagement/v9");
 
// Your account login
define("DEVELOPER_TOKEN", "BBD37VB98");
$username = "YOUR_USERNAME";
$password = "YOUR_PASSWORD";
$accountId = "YOUR_ACCOUNT_ID";
 
// The last time you updated your system (null to extract everything)
$lastSyncDate = null;
 
// The download filename
$zipFilename = "/tmp/bulk_download.zip";
 
/*
 * Create a PHP SOAP Client for the Bing Ads API Bulk Service
 */
 
// Create the client
$client = new \SoapClient(BULK_API_ENDPOINT);
 
// Set the Authentication headers
$headers = array();
$headers[] = new \SoapHeader(API_NAMESPACE, "UserName", $username);
$headers[] = new \SoapHeader(API_NAMESPACE, "Password", $password);
$headers[] = new \SoapHeader(API_NAMESPACE, "DeveloperToken", DEVELOPER_TOKEN);
$headers[] = new \SoapHeader(API_NAMESPACE, "CustomerAccountId", $accountId);
$client->__setSoapHeaders($headers);
 
/*
 * Request a bulk download file
 */
 
// Create a Bulk Download request 
$downloadRequest = array(
    "AccountIds" => array(new \SoapVar($accountId, XSD_LONG, 'xsd:long')),
    "DownloadFileType" => "Tsv",
    "Entities" => "Campaigns AdGroups Ads Keywords"
);
 
// Set the last request date if it's available
if ($lastSyncDate !== null) {
    $downloadRequest["LastSyncTimeInUTC"] = date("c", $lastSyncDate);
}
 
// Call the API
print "Requesting a download file for account: '$accountId'\n";
$response = $client->DownloadCampaignsByAccountIds($downloadRequest);
 
// Extract the request ID
$requestId = $response->DownloadRequestId;
print "Request submitted with request ID of '$requestId'\n";
 
/*
 * Wait for the file to be created
 */
 
// Create a status request using the request ID
$statusRequest = array(
    "DownloadRequestId" => $requestId
);
 
// Wait until the file is ready
for ($pollDelay = 60, $status = "InProgress"; $status === "InProgress"; $pollDelay *= 1.5) {
    // Wait for the delay timeout
    print "Waiting for $pollDelay seconds…\n";
    sleep($pollDelay);
 
    // Call the API
    $response = $client->GetDownloadStatus($statusRequest);
 
    // Extract the status of the download file
    $status = $response->RequestStatus;
    print "Current status is '$status'\n";
}
 
// Extract the download URL
$downloadUrl = $response->DownloadUrl;
print "Download URL is '$downloadUrl'\n";
 
/*
 * Download the file
 */
// Create a cURL request for the download URL
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $downloadUrl);
curl_setopt($curl, CURLOPT_HEADER, false);
curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
 
// Set the SSL version used by Microsoft
curl_setopt($curl, CURLOPT_SSLVERSION, 3);
 
// Download the file to the zip file
$file = curl_exec($curl);
curl_close($curl);
file_put_contents($zipFilename, $file);
 
// Extract the file
$zip = new \ZipArchive();
$zip->open($zipFilename);
 
// Process the rows in the file
$rows = explode("\n", trim($zip->getFromIndex(0)));
$headerRow = array_shift($rows);
 
foreach ($rows as $row) {
    $row = explode("\t", $row);
    print "Extracted {$row[0]} with an ID of '{$row[2]}'\n";
}
 
$zip->close();
 
print "Finished!\n";
?>
Downloading Campaigns from the Bing Ads API

Comments

I'm keen to get feedback on my posts, so if you have any questions or comments, then please send me a message and I'll be happy to help.