Skip to content

Commit

Permalink
✨ Source Bing Ads: Stream budget and product dimension performance re…
Browse files Browse the repository at this point in the history
…port (#35201)
  • Loading branch information
darynaishchenko authored Mar 1, 2024
1 parent 9f28113 commit bcf32a2
Show file tree
Hide file tree
Showing 41 changed files with 1,353 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,14 @@ acceptance_tests:
expect_records:
path: "integration_tests/expected_records.jsonl"
empty_streams:
- name: product_dimension_performance_report_hourly
bypass_reason: "Test Account doesn't have Merchant Center configured to add Products, testing in integration test"
- name: product_dimension_performance_report_daily
bypass_reason: "Test Account doesn't have Merchant Center configured to add Products, testing in integration test"
- name: product_dimension_performance_report_weekly
bypass_reason: "Test Account doesn't have Merchant Center configured to add Products, testing in integration test"
- name: product_dimension_performance_report_monthly
bypass_reason: "Test Account doesn't have Merchant Center configured to add Products, testing in integration test"
- name: account_performance_report_hourly
bypass_reason: "Hourly reports are disabled, because sync is too long"
- name: ad_group_performance_report_hourly
Expand Down Expand Up @@ -94,6 +102,14 @@ acceptance_tests:
expect_records:
path: "integration_tests/expected_records_no_start_date.jsonl"
empty_streams:
- name: product_dimension_performance_report_hourly
bypass_reason: "Test Account doesn't have Merchant Center configured to add Products, testing in integration test"
- name: product_dimension_performance_report_daily
bypass_reason: "Test Account doesn't have Merchant Center configured to add Products, testing in integration test"
- name: product_dimension_performance_report_weekly
bypass_reason: "Test Account doesn't have Merchant Center configured to add Products, testing in integration test"
- name: product_dimension_performance_report_monthly
bypass_reason: "Test Account doesn't have Merchant Center configured to add Products, testing in integration test"
- name: app_install_ads
bypass_reason: "Can not populate; new campaign with link to app needed; feature is not available yet"
- name: app_install_ad_labels
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,16 @@
"sync_mode": "full_refresh",
"destination_sync_mode": "append"
},
{
"stream": {
"name": "budget",
"json_schema": {},
"supported_sync_modes": ["full_refresh", "incremental"]
},
"sync_mode": "incremental",
"cursor_field": ["Modified Time"],
"destination_sync_mode": "append"
},
{
"stream": {
"name": "campaigns",
Expand Down Expand Up @@ -585,6 +595,46 @@
"sync_mode": "incremental",
"cursor_field": ["TimePeriod"],
"destination_sync_mode": "append"
},
{
"stream": {
"name": "product_dimension_performance_report_hourly",
"json_schema": {},
"supported_sync_modes": ["incremental", "full_refresh"]
},
"sync_mode": "incremental",
"cursor_field": ["TimePeriod"],
"destination_sync_mode": "append"
},
{
"stream": {
"name": "product_dimension_performance_report_daily",
"json_schema": {},
"supported_sync_modes": ["incremental", "full_refresh"]
},
"sync_mode": "incremental",
"cursor_field": ["TimePeriod"],
"destination_sync_mode": "append"
},
{
"stream": {
"name": "product_dimension_performance_report_weekly",
"json_schema": {},
"supported_sync_modes": ["incremental", "full_refresh"]
},
"sync_mode": "incremental",
"cursor_field": ["TimePeriod"],
"destination_sync_mode": "append"
},
{
"stream": {
"name": "product_dimension_performance_report_monthly",
"json_schema": {},
"supported_sync_modes": ["incremental", "full_refresh"]
},
"sync_mode": "incremental",
"cursor_field": ["TimePeriod"],
"destination_sync_mode": "append"
}
]
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,4 @@
{"stream":"user_location_performance_report_weekly","data":{"AccountName":"Airbyte","AccountNumber":"F149MJ18","AccountId":180519267,"TimePeriod":"2023-12-17","CampaignName":"Airbyte test","CampaignId":531016227,"AdGroupName":"keywords","AdGroupId":1356799861840328,"Country":"United Arab Emirates","State":"Dubai","MetroArea":null,"CurrencyCode":"USD","AdDistribution":"Audience","Impressions":1,"Clicks":0,"Ctr":0.0,"AverageCpc":0.0,"Spend":0.0,"AveragePosition":0.0,"ProximityTargetLocation":null,"Radius":0,"Language":"English","City":"Dubai","QueryIntentCountry":"United Arab Emirates","QueryIntentState":null,"QueryIntentCity":null,"QueryIntentDMA":null,"BidMatchType":"Broad","DeliveredMatchType":"Exact","Network":"Audience","TopVsOther":"Audience network","DeviceType":"Smartphone","DeviceOS":"Android","Assists":0,"Conversions":0,"ConversionRate":null,"Revenue":0.0,"ReturnOnAdSpend":null,"CostPerConversion":null,"CostPerAssist":null,"RevenuePerConversion":null,"RevenuePerAssist":null,"County":null,"PostalCode":null,"QueryIntentCounty":null,"QueryIntentPostalCode":null,"LocationId":154645,"QueryIntentLocationId":218,"AllConversions":0,"AllRevenue":0.0,"AllConversionRate":null,"AllCostPerConversion":null,"AllReturnOnAdSpend":null,"AllRevenuePerConversion":null,"ViewThroughConversions":0,"Goal":null,"GoalType":null,"AbsoluteTopImpressionRatePercent":0.0,"TopImpressionRatePercent":0.0,"AverageCpm":0.0,"ConversionsQualified":0.0,"AllConversionsQualified":0.0,"ViewThroughConversionsQualified":null,"Neighborhood":null,"QueryIntentNeighborhood":null,"ViewThroughRevenue":0.0,"CampaignType":"Search & content","AssetGroupId":null,"AssetGroupName":null},"emitted_at":1704833830043}
{"stream":"account_impression_performance_report_daily","data":{"AccountName":"Airbyte","AccountNumber":"F149MJ18","AccountId":180519267,"TimePeriod":"2023-12-18","CurrencyCode":"USD","AdDistribution":"Search","Impressions":22,"Clicks":0,"Ctr":0.0,"AverageCpc":0.0,"Spend":0.0,"AveragePosition":0.0,"Conversions":0,"ConversionRate":null,"CostPerConversion":null,"LowQualityClicks":0,"LowQualityClicksPercent":null,"LowQualityImpressions":6,"LowQualityImpressionsPercent":21.43,"LowQualityConversions":0,"LowQualityConversionRate":null,"DeviceType":"Computer","ImpressionSharePercent":34.92,"ImpressionLostToBudgetPercent":1.59,"ImpressionLostToRankAggPercent":63.49,"PhoneImpressions":0,"PhoneCalls":0,"Ptr":null,"Network":"Syndicated search partners","Assists":0,"Revenue":0.0,"ReturnOnAdSpend":null,"CostPerAssist":null,"RevenuePerConversion":null,"RevenuePerAssist":null,"AccountStatus":"Active","LowQualityGeneralClicks":0,"LowQualitySophisticatedClicks":0,"ExactMatchImpressionSharePercent":5.26,"ClickSharePercent":null,"AbsoluteTopImpressionSharePercent":10.2,"TopImpressionShareLostToRankPercent":68.0,"TopImpressionShareLostToBudgetPercent":0.0,"AbsoluteTopImpressionShareLostToRankPercent":89.8,"AbsoluteTopImpressionShareLostToBudgetPercent":0.0,"TopImpressionSharePercent":32.0,"AbsoluteTopImpressionRatePercent":22.73,"TopImpressionRatePercent":72.73,"AllConversions":0,"AllRevenue":0.0,"AllConversionRate":null,"AllCostPerConversion":null,"AllReturnOnAdSpend":null,"AllRevenuePerConversion":null,"ViewThroughConversions":0,"AudienceImpressionSharePercent":null,"AudienceImpressionLostToRankPercent":null,"AudienceImpressionLostToBudgetPercent":null,"AverageCpm":0.0,"ConversionsQualified":0.0,"LowQualityConversionsQualified":0.0,"AllConversionsQualified":0.0,"ViewThroughConversionsQualified":null,"ViewThroughRevenue":0.0,"VideoViews":0,"ViewThroughRate":0.0,"AverageCPV":null,"VideoViewsAt25Percent":0,"VideoViewsAt50Percent":0,"VideoViewsAt75Percent":0,"CompletedVideoViews":0,"VideoCompletionRate":0.0,"TotalWatchTimeInMS":0,"AverageWatchTimePerVideoView":null,"AverageWatchTimePerImpression":0.0,"Sales":0,"CostPerSale":null,"RevenuePerSale":null,"Installs":0,"CostPerInstall":null,"RevenuePerInstall":null},"emitted_at":1704833886551}
{"stream":"account_impression_performance_report_weekly","data":{"AccountName":"Airbyte","AccountNumber":"F149MJ18","AccountId":180519267,"TimePeriod":"2023-12-17","CurrencyCode":"USD","AdDistribution":"Search","Impressions":639,"Clicks":14,"Ctr":2.19,"AverageCpc":0.12,"Spend":1.74,"AveragePosition":0.0,"Conversions":0,"ConversionRate":0.0,"CostPerConversion":null,"LowQualityClicks":6,"LowQualityClicksPercent":30.0,"LowQualityImpressions":53,"LowQualityImpressionsPercent":7.66,"LowQualityConversions":0,"LowQualityConversionRate":0.0,"DeviceType":"Computer","ImpressionSharePercent":13.57,"ImpressionLostToBudgetPercent":17.96,"ImpressionLostToRankAggPercent":68.47,"PhoneImpressions":0,"PhoneCalls":0,"Ptr":null,"Network":"Syndicated search partners","Assists":0,"Revenue":0.0,"ReturnOnAdSpend":0.0,"CostPerAssist":null,"RevenuePerConversion":null,"RevenuePerAssist":null,"AccountStatus":"Active","LowQualityGeneralClicks":0,"LowQualitySophisticatedClicks":6,"ExactMatchImpressionSharePercent":17.65,"ClickSharePercent":1.28,"AbsoluteTopImpressionSharePercent":3.2,"TopImpressionShareLostToRankPercent":74.15,"TopImpressionShareLostToBudgetPercent":18.25,"AbsoluteTopImpressionShareLostToRankPercent":78.51,"AbsoluteTopImpressionShareLostToBudgetPercent":18.29,"TopImpressionSharePercent":7.6,"AbsoluteTopImpressionRatePercent":22.69,"TopImpressionRatePercent":53.99,"AllConversions":0,"AllRevenue":0.0,"AllConversionRate":0.0,"AllCostPerConversion":null,"AllReturnOnAdSpend":0.0,"AllRevenuePerConversion":null,"ViewThroughConversions":0,"AudienceImpressionSharePercent":null,"AudienceImpressionLostToRankPercent":null,"AudienceImpressionLostToBudgetPercent":null,"AverageCpm":2.72,"ConversionsQualified":0.0,"LowQualityConversionsQualified":0.0,"AllConversionsQualified":0.0,"ViewThroughConversionsQualified":null,"ViewThroughRevenue":0.0,"VideoViews":0,"ViewThroughRate":0.0,"AverageCPV":null,"VideoViewsAt25Percent":0,"VideoViewsAt50Percent":0,"VideoViewsAt75Percent":0,"CompletedVideoViews":0,"VideoCompletionRate":0.0,"TotalWatchTimeInMS":0,"AverageWatchTimePerVideoView":null,"AverageWatchTimePerImpression":0.0,"Sales":0,"CostPerSale":null,"RevenuePerSale":null,"Installs":0,"CostPerInstall":null,"RevenuePerInstall":null},"emitted_at":1704833908003}
{"stream": "budget", "data": {"Type": "Budget", "Status": "Active", "Id": 10239202868095, "Parent Id": 180519267, "Client Id": null, "Modified Time": "2024-02-28T17:52:08.900+00:00", "Budget Id": null, "Budget Name": "Test Shared Budget", "Budget": 2.0, "Budget Type": "DailyBudgetStandard", "Account Id": 180519267}, "emitted_at": 1709228203331}
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@
{"stream": "ad_group_labels", "data": {"Status": "Active", "Id": 10239203506495, "Parent Id": 1350201453189474, "Campaign": null, "Ad Group": null, "Client Id": null, "Modified Time": "2023-04-27T18:00:14.970+00:00", "Account Id": 180278106}, "emitted_at": 1701982478843}
{"stream": "labels", "data": {"Status": "Active", "Id": 10239203506496, "Client Id": null, "Modified Time": "2023-04-27T17:16:53.430+00:00", "Description": null, "Label": "campaign label 2", "Color": "#D8558B", "Account Id": 180278106}, "emitted_at": 1701982532098}
{"stream": "campaign_labels", "data": {"Status": "Active", "Id": 10239203506495, "Parent Id": 413732450, "Campaign": null, "Client Id": null, "Modified Time": "2023-04-27T17:57:21.497+00:00", "Account Id": 180278106}, "emitted_at": 1701982600348}
{"stream": "budget", "data": {"Type": "Budget", "Status": "Active", "Id": 10239202868095, "Parent Id": 180519267, "Client Id": null, "Modified Time": "2024-02-28T17:52:08.900+00:00", "Budget Id": null, "Budget Name": "Test Shared Budget", "Budget": 2.0, "Budget Type": "DailyBudgetStandard", "Account Id": 180519267}, "emitted_at": 1709228203331}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ data:
connectorSubtype: api
connectorType: source
definitionId: 47f25999-dd5e-4636-8c39-e7cea2453331
dockerImageTag: 2.1.4
dockerImageTag: 2.2.0
dockerRepository: airbyte/source-bing-ads
documentationUrl: https://docs.airbyte.com/integrations/sources/bing-ads
githubIssueLabel: source-bing-ads
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ requires = [ "poetry-core>=1.0.0",]
build-backend = "poetry.core.masonry.api"

[tool.poetry]
version = "2.1.4"
version = "2.2.0"
name = "source-bing-ads"
description = "Source implementation for Bing Ads."
authors = [ "Airbyte <[email protected]>",]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -196,3 +196,12 @@ class AdGroupLabels(BingAdsBulkStream):

data_scope = ["EntityData"]
download_entities = ["AdGroupLabels"]


class Budget(BingAdsBulkStream):
"""
https://learn.microsoft.com/en-us/advertising/bulk-service/budget?view=bingads-13&viewFallbackFrom=bingads-13
"""

data_scope = ["EntityData"]
download_entities = ["Budgets"]
Original file line number Diff line number Diff line change
Expand Up @@ -670,6 +670,45 @@ class UserLocationPerformanceReportMonthly(UserLocationPerformanceReport):
report_aggregation = "Monthly"


class ProductDimensionPerformanceReport(BingAdsReportingServicePerformanceStream, ABC):
"""
https://learn.microsoft.com/en-us/advertising/reporting-service/productdimensionperformancereportrequest?view=bingads-13
"""

report_name: str = "ProductDimensionPerformanceReport"
report_schema_name = "product_dimension_performance_report"
primary_key = None

@property
def report_columns(self) -> Iterable[str]:
"""AccountId is not in reporting columns for this report"""
properties = list(self.get_json_schema().get("properties", {}).keys())
properties.remove("AccountId")
return properties

def transform(self, record: MutableMapping[str, Any], stream_slice: Mapping[str, Any], **kwargs) -> MutableMapping[str, Any]:
record = super().transform(record, stream_slice)
record["AccountId"] = stream_slice["account_id"]
return record


class ProductDimensionPerformanceReportHourly(HourlyReportTransformerMixin, ProductDimensionPerformanceReport):
report_aggregation = "Hourly"
report_schema_name = "product_dimension_performance_report_hourly"


class ProductDimensionPerformanceReportDaily(ProductDimensionPerformanceReport):
report_aggregation = "Daily"


class ProductDimensionPerformanceReportWeekly(ProductDimensionPerformanceReport):
report_aggregation = "Weekly"


class ProductDimensionPerformanceReportMonthly(ProductDimensionPerformanceReport):
report_aggregation = "Monthly"


class CustomReport(BingAdsReportingServicePerformanceStream, ABC):
transformer: TypeTransformer = TypeTransformer(TransformConfig.DefaultSchemaNormalization)
custom_report_columns = []
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
{
"$schema": "https://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"Account Id": {
"type": ["null", "integer"]
},
"Type": {
"type": ["null", "string"]
},
"Status": {
"type": ["null", "string"]
},
"Id": {
"type": ["null", "integer"]
},
"Parent Id": {
"type": ["null", "integer"]
},
"Client Id": {
"type": ["null", "integer"]
},
"Modified Time": {
"type": ["null", "string"],
"format": "date-time",
"airbyte_type": "timestamp_with_timezone"
},
"Budget Id": {
"type": ["null", "integer"]
},
"Budget Name": {
"type": ["null", "string"]
},
"Budget": {
"type": ["null", "number"]
},
"Budget Type": {
"type": ["null", "string"]
}
}
}
Loading

0 comments on commit bcf32a2

Please sign in to comment.