Skip to main content

📊 Bing Ads - Campaign Management

📖 Overview

The Campaign Management Service provides SOAP-based operations for retrieving campaign information and generating performance reports. Supports Search, Shopping, and DynamicSearchAds campaign types with asynchronous report generation.

Source Files:

  • Controller: external/Integrations/BingAds/Controllers/Campaigns/CampaignController.js
  • Model: external/Integrations/BingAds/Models/Campaigns/CampaignsModel.js
  • Routes: external/Integrations/BingAds/Routes/campaigns.js

External APIs:

  • Campaign Management Service: https://campaign.api.bingads.microsoft.com/Api/Advertiser/CampaignManagement/v13/CampaignManagementService.svc
  • Reporting Service: https://reporting.api.bingads.microsoft.com/Api/Advertiser/Reporting/v13/ReportingService.svc

🔄 Data Flow

sequenceDiagram
participant Client as API Client
participant DC as DashClicks API
participant MW as Token Middleware
participant Model as CampaignsModel
participant SOAP as Bing SOAP API

Client->>DC: GET /campaigns
DC->>MW: Check token expiration
MW->>DC: Valid access token
DC->>Model: getCampaignsByAccountId()
Model->>Model: Build SOAP XML request
Model->>SOAP: POST to Campaign Management Service
SOAP-->>Model: SOAP XML response with campaigns
Model->>Model: Parse XML to JSON
Model-->>DC: Return campaign array
DC-->>Client: JSON response

🔧 Campaign Functions

List Campaigns by Account

GET /campaigns

Purpose: Retrieve all campaigns for a specific account, optionally filtered by campaign type

Controller: CampaignController.index()

Model Method: CampaignsModel.getCampaignsByAccountId(customerAccountID, customerID, campaignType)

SOAP Operation: GetCampaignsByAccountId

Request:

GET /v1/integrations/bing/ads/campaigns?customerAccountID=111222333&customerID=123456&campaignType=Search
Authorization: Bearer {jwt_token}

Query Parameters:

ParameterTypeRequiredDescription
customerAccountIDIntegerAccount ID from /accessible-user-accounts
customerIDIntegerCustomer ID (optional but recommended)
campaignTypeStringFilter: Search, Shopping, DynamicSearchAds

Validation:

  • If customerAccountID missing, returns error: "Please provide customerAccountID optionaly you can provide customerID and campaignType as well as"

SOAP Request XML:

<s:Envelope xmlns:i="http://www.w3.org/2001/XMLSchema-instance"
xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Header xmlns="https://bingads.microsoft.com/CampaignManagement/v13">
<Action mustUnderstand="1">GetCampaignsByAccountId</Action>
<AuthenticationToken i:nil="false">{ACCESS_TOKEN}</AuthenticationToken>
<CustomerAccountId i:nil="false">111222333</CustomerAccountId>
<CustomerId i:nil="true">123456</CustomerId>
<DeveloperToken i:nil="false">{DEVELOPER_TOKEN}</DeveloperToken>
</s:Header>
<s:Body>
<GetCampaignsByAccountIdRequest xmlns="https://bingads.microsoft.com/CampaignManagement/v13">
<AccountId>111222333</AccountId>
<!-- If campaignType not provided, defaults to all 3 types -->
<CampaignType>Search</CampaignType>
<CampaignType>Shopping</CampaignType>
<CampaignType>DynamicSearchAds</CampaignType>
</GetCampaignsByAccountIdRequest>
</s:Body>
</s:Envelope>

Campaign Type Filter:

  • If campaignType provided: <CampaignType>{campaignType}</CampaignType>
  • If not provided: All three types included (Search, Shopping, DynamicSearchAds)

SOAP Response Structure:

<s:Envelope>
<s:Body>
<GetCampaignsByAccountIdResponse>
<Campaigns>
<Campaign i:type="SearchCampaign">
<CampaignId>987654321</CampaignId>
<Name>Search Campaign Name</Name>
<Status>Active</Status>
<TimeZone>EasternTimeUSCanada</TimeZone>
<BudgetType>DailyBudgetStandard</BudgetType>
<DailyBudget>50.00</DailyBudget>
<Languages>
<string>English</string>
</Languages>
<Settings>
<Setting i:type="TargetSetting">...</Setting>
</Settings>
<BiddingScheme i:type="ManualCpcBiddingScheme">...</BiddingScheme>
</Campaign>
<Campaign i:type="ShoppingCampaign">
<CampaignId>555666777</CampaignId>
<Name>Shopping Campaign</Name>
<Status>Active</Status>
<Settings>
<Setting i:type="ShoppingSetting">
<Priority>0</Priority>
<StoreId>12345</StoreId>
</Setting>
</Settings>
</Campaign>
</Campaigns>
</GetCampaignsByAccountIdResponse>
</s:Body>
</s:Envelope>

JSON Response (Parsed from SOAP XML):

{
"success": true,
"message": "SUCCESS",
"data": [
{
"CampaignId": 987654321,
"Name": "Search Campaign Name",
"Status": "Active",
"TimeZone": "EasternTimeUSCanada",
"BudgetType": "DailyBudgetStandard",
"DailyBudget": 50.00,
"Languages": {
"string": ["English"]
},
"Settings": { ... },
"BiddingScheme": { ... }
},
{
"CampaignId": 555666777,
"Name": "Shopping Campaign",
"Status": "Active",
"Settings": {
"Setting": {
"Priority": 0,
"StoreId": 12345
}
}
}
]
}

Key Response Fields:

FieldTypeDescription
CampaignIdIntegerUnique campaign identifier
NameStringCampaign name
StatusStringActive, Paused, Deleted, Suspended
TimeZoneStringCampaign timezone
BudgetTypeStringDailyBudgetStandard, DailyBudgetAccelerated
DailyBudgetDecimalDaily budget amount
LanguagesArrayTarget languages
BiddingSchemeObjectBidding strategy details
SettingsObjectCampaign-specific settings

Side Effects:

  • None (read-only operation)

Get Campaign by ID

GET /campaigns/{campaignID}

Purpose: Retrieve specific campaign(s) by ID(s)

Controller: CampaignController.show()

Model Method: CampaignsModel.getCampaignsByIds(customerAccountID, customerID, campaignID, campaignType)

SOAP Operation: GetCampaignsByIds

Request:

GET /v1/integrations/bing/ads/campaigns/987654321?customerAccountID=111222333&customerID=123456
Authorization: Bearer {jwt_token}

Query Parameters:

ParameterTypeRequiredDescription
customerAccountIDIntegerAccount ID
customerIDIntegerCustomer ID
campaignIDStringCampaign ID(s) comma-separated (max 100)
campaignTypeStringFilter by campaign type

Validation:

  • If any required param missing, returns error: "Please provide customerAccountID,customerID and campaignID."

Multiple Campaign IDs:

GET /campaigns/987654321,555666777,111222333?customerAccountID=...&customerID=...

SOAP Request XML:

<s:Envelope xmlns:i="http://www.w3.org/2001/XMLSchema-instance"
xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Header xmlns="https://bingads.microsoft.com/CampaignManagement/v13">
<Action mustUnderstand="1">GetCampaignsByIds</Action>
<AuthenticationToken i:nil="false">{ACCESS_TOKEN}</AuthenticationToken>
<CustomerAccountId i:nil="false">111222333</CustomerAccountId>
<CustomerId i:nil="false">123456</CustomerId>
<DeveloperToken i:nil="false">{DEVELOPER_TOKEN}</DeveloperToken>
</s:Header>
<s:Body>
<GetCampaignsByIdsRequest xmlns="https://bingads.microsoft.com/CampaignManagement/v13">
<AccountId>111222333</AccountId>
<CampaignIds i:nil="false" xmlns:a1="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
<a1:long>987654321</a1:long>
<a1:long>555666777</a1:long>
</CampaignIds>
<CampaignType>Search</CampaignType>
<CampaignType>Shopping</CampaignType>
<CampaignType>DynamicSearchAds</CampaignType>
</GetCampaignsByIdsRequest>
</s:Body>
</s:Envelope>

Helper Method: generateCampaignIdsXml(campaignID)

  • Splits comma-separated IDs
  • Generates XML: <a1:long>{id}</a1:long> for each ID

JSON Response:

{
"success": true,
"message": "SUCCESS",
"data": {
"CampaignId": 987654321,
"Name": "Specific Campaign",
"Status": "Active",
"DailyBudget": 75.00,
"TimeZone": "PacificTimeUSCanada",
"BiddingScheme": {
"@i:type": "ManualCpcBiddingScheme"
}
}
}

Note: If multiple IDs provided, response is array; if single ID, response is object.


Get Campaign Performance Metrics

GET /campaigns/metrics

Purpose: Generate asynchronous performance report for campaigns

Controller: CampaignController.metrics()

Model Method: CampaignsModel.reports(...)

SOAP Operation: SubmitGenerateReport

Service: Reporting Service v13 (different endpoint)

Request:

GET /v1/integrations/bing/ads/campaigns/metrics?customerAccountID=111222333&customerID=123456&aggregation=Daily&predefinedTime=Last7Days&timeZone=EasternTimeUSCanada
Authorization: Bearer {jwt_token}

Query Parameters:

ParameterTypeRequiredDescriptionDefault
customerAccountIDIntegerAccount ID-
customerIDIntegerCustomer ID-
campaignIDIntegerSpecific campaign IDAll campaigns
adGroupIDIntegerSpecific ad group IDAll ad groups
aggregationStringAggregation levelMonthly
predefinedTimeStringPredefined time periodLast30Days
timeZoneStringReport timezoneEasternTimeUSCanada
fromDateStringCustom start date (YYYY-MM-DD)-
endDateStringCustom end date (YYYY-MM-DD)-

Aggregation Options:

  • Hourly - Hourly breakdowns
  • Daily - Daily breakdowns
  • Weekly - Weekly breakdowns
  • Monthly - Monthly breakdowns (default)
  • Yearly - Yearly breakdowns
  • Summary - Total summary

Predefined Time Periods:

  • Today, Yesterday
  • LastSevenDays, ThisWeek, LastWeek
  • LastFourWeeks, ThisMonth, LastMonth
  • LastThreeMonths, LastSixMonths
  • ThisYear, LastYear
  • Last30Days (default)

Custom Date Range:

# Uses fromDate and endDate instead of predefinedTime
GET /campaigns/metrics?customerAccountID=...&fromDate=2024-01-01&endDate=2024-01-31

SOAP Request XML:

<s:Envelope xmlns:i="http://www.w3.org/2001/XMLSchema-instance"
xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Header xmlns="https://bingads.microsoft.com/Reporting/v13">
<Action mustUnderstand="1">SubmitGenerateReport</Action>
<AuthenticationToken i:nil="false">{ACCESS_TOKEN}</AuthenticationToken>
<CustomerAccountId i:nil="false">111222333</CustomerAccountId>
<CustomerId i:nil="true">123456</CustomerId>
<DeveloperToken i:nil="false">{DEVELOPER_TOKEN}</DeveloperToken>
</s:Header>
<s:Body>
<SubmitGenerateReportRequest xmlns="https://bingads.microsoft.com/Reporting/v13">
<ReportRequest i:nil="false" i:type="CampaignPerformanceReportRequest">
<ExcludeColumnHeaders>false</ExcludeColumnHeaders>
<ExcludeReportFooter>false</ExcludeReportFooter>
<ExcludeReportHeader>false</ExcludeReportHeader>
<Format>Csv</Format>
<Language>English</Language>
<ReportName>CampaignPerformanceReportRequest</ReportName>
<ReturnOnlyCompleteData>false</ReturnOnlyCompleteData>
<Aggregation>Daily</Aggregation>
<Columns>
<CampaignPerformanceReportColumn>AccountName</CampaignPerformanceReportColumn>
<CampaignPerformanceReportColumn>CampaignId</CampaignPerformanceReportColumn>
<CampaignPerformanceReportColumn>CampaignName</CampaignPerformanceReportColumn>
<CampaignPerformanceReportColumn>Impressions</CampaignPerformanceReportColumn>
<CampaignPerformanceReportColumn>Clicks</CampaignPerformanceReportColumn>
<CampaignPerformanceReportColumn>Ctr</CampaignPerformanceReportColumn>
<CampaignPerformanceReportColumn>Spend</CampaignPerformanceReportColumn>
<!-- 60+ more columns available -->
</Columns>
<Filter i:nil="true"/>
<Scope>
<AccountIds xmlns:a1="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
<a1:long>111222333</a1:long>
</AccountIds>
<!-- Optional: Specific campaign and ad group -->
<Campaigns i:nil="false">
<CampaignReportScope>
<AccountId>111222333</AccountId>
<CampaignId>987654321</CampaignId>
</CampaignReportScope>
</Campaigns>
</Scope>
<Time>
<PredefinedTime i:nil="false">Last7Days</PredefinedTime>
<ReportTimeZone>EasternTimeUSCanada</ReportTimeZone>
</Time>
</ReportRequest>
</SubmitGenerateReportRequest>
</s:Body>
</s:Envelope>

Available Report Columns (67 total):

ColumnDescription
AccountName, AccountNumber, AccountIdAccount identifiers
CampaignId, CampaignName, CampaignStatusCampaign info
Impressions, Clicks, CtrCore metrics
Spend, AverageCpc, AveragePositionCost metrics
Conversions, ConversionRate, CostPerConversionConversion metrics
Revenue, ReturnOnAdSpend, RevenuePerConversionRevenue metrics
QualityScore, ExpectedCtr, AdRelevance, LandingPageExperienceQuality metrics
AllConversions, AllRevenue, ViewThroughConversionsAdvanced conversion tracking
Goal, GoalType, TimePeriodReporting metadata

Full columns list: See getCampaignColumns() method in source code (67 columns total)

Custom Date XML Generation:

// Helper: generateCustomDateXML(fromDate, endDate, predefinedTime)

// Option 1: Predefined Time
<PredefinedTime i:nil="false">Last30Days</PredefinedTime>

// Option 2: Custom Date Range
<CustomDateRangeEnd>
<Day>31</Day>
<Month>01</Month>
<Year>2024</Year>
</CustomDateRangeEnd>
<CustomDateRangeStart>
<Day>01</Day>
<Month>01</Month>
<Year>2024</Year>
</CustomDateRangeStart>

SOAP Response Structure:

<s:Envelope>
<s:Body>
<SubmitGenerateReportResponse>
<ReportRequestId>987654321012345</ReportRequestId>
</SubmitGenerateReportResponse>
</s:Body>
</s:Envelope>

JSON Response:

{
"success": true,
"message": "SUCCESS",
"data": {
"ReportRequestId": "987654321012345"
}
}

Important: This is an asynchronous operation:

  1. Returns ReportRequestId immediately
  2. Report generation happens in background
  3. Must poll PollGenerateReport to check status
  4. When Success, download CSV via ReportRequestId

Report Download Flow:

  1. Submit report request → Get ReportRequestId
  2. Poll status with ReportRequestId → Check if Success
  3. Download CSV report using ReportRequestId

📊 Campaign Types

TypeDescriptionUse Case
SearchText ads on Bing search resultsKeyword-based advertising
ShoppingProduct ads with images and pricesE-commerce product listings
DynamicSearchAdsAuto-generated ads from website contentLarge inventories, dynamic content

🕒 Time Zones

Common Options:

  • EasternTimeUSCanada (default)
  • PacificTimeUSCanada
  • CentralTimeUSCanada
  • MountainTimeUSCanada
  • GMTStandardTime (UTC)
  • See Microsoft Timezone Reference

🔄 Helper Methods

generateCampaignIdsXml(campaignID)

Converts comma-separated campaign IDs to SOAP XML format.

Input: "987654321,555666777"

Output:

<a1:long>987654321</a1:long>
<a1:long>555666777</a1:long>

generateAccountIdXml(accountID)

Converts comma-separated account IDs to SOAP XML format (for reporting scope).

generateCustomDateXML(fromDate, endDate, predefinedTime)

Generates date range XML based on input:

  • If predefinedTime provided: Uses predefined period
  • If fromDate and endDate provided: Custom date range XML
  • If neither: Defaults to Last30Days

getCampaignColumns()

Returns array of 67 available report column names.

⚠️ Important Notes

  • 📊 Async Reporting: Metrics endpoint returns request ID, not actual data
  • 🕒 Report Polling: Must implement polling to check report completion
  • 📁 CSV Format: Reports returned as CSV files (Format: Csv)
  • 🔢 Max Campaign IDs: Can request up to 100 campaign IDs per call
  • 🎯 Campaign Type Defaults: If not specified, includes Search, Shopping, DynamicSearchAds
  • 📅 Date Format: Custom dates must be YYYY-MM-DD format
  • 🔐 Two Tokens Required: OAuth access token + developer token
  • 🌍 Timezone: Affects date range interpretation (use account timezone)
  • 📊 67 Metrics Available: Full list in getCampaignColumns()
  • 🔄 Token Auto-Refresh: Middleware ensures valid tokens
  • 🏗️ SOAP Protocol: XML requests/responses (parsed to JSON)
  • 📝 Report Download: Requires separate API call (not implemented in this endpoint)
💬

Documentation Assistant

Ask me anything about the docs

Hi! I'm your documentation assistant. Ask me anything about the docs!

I can help you with:
- Code examples
- Configuration details
- Troubleshooting
- Best practices

Try asking: How do I configure the API?
09:30 AM