Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

✨ Source Bing Ads: Stream budget and product dimension performance report #35201

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
b3ddb10
added stream budget
darynaishchenko Feb 13, 2024
a3b14d9
added stream product dimensaion
darynaishchenko Feb 13, 2024
8c5d87a
updated streams
darynaishchenko Feb 13, 2024
1ae6396
added integration tests for new streams
darynaishchenko Feb 13, 2024
d3a6232
added resourse data for tests
darynaishchenko Feb 13, 2024
cb66910
updated streams value in unit test
darynaishchenko Feb 13, 2024
ead65d6
updated cat config with new streams
darynaishchenko Feb 13, 2024
3463422
updated docs and metadata
darynaishchenko Feb 13, 2024
3cb5312
format fix
darynaishchenko Feb 13, 2024
00a75a8
Merge branch 'master' into daryna/source-bing-ads/stream-budget-and-p…
darynaishchenko Feb 13, 2024
d73596e
updated changelog
darynaishchenko Feb 13, 2024
95d8e24
fixed cat config
darynaishchenko Feb 13, 2024
571146e
refactored code
darynaishchenko Feb 19, 2024
121cdbf
added BaseTest, updated TestBulkStreams and TestreportStreams
darynaishchenko Feb 20, 2024
897d2c3
updated client mock logic
darynaishchenko Feb 20, 2024
b07be18
fix hints
darynaishchenko Feb 20, 2024
92bb09d
updated product_dimension_performance_report data
darynaishchenko Feb 21, 2024
7b11e0f
updated TestSuiteReportStream with skipp for base test
darynaishchenko Feb 21, 2024
ba7c69d
remove redundant headers
darynaishchenko Feb 21, 2024
5d2f8fd
format fix
darynaishchenko Feb 21, 2024
4616384
updated state for streams
darynaishchenko Feb 21, 2024
ebd0921
deleted catalog builder
darynaishchenko Feb 21, 2024
c48aa81
updated BaseTest
darynaishchenko Feb 21, 2024
f4bae3b
updated response data
darynaishchenko Feb 21, 2024
a895fa4
updated TestBudgetStream
darynaishchenko Feb 21, 2024
e9346de
updated TestSuiteReportStream
darynaishchenko Feb 21, 2024
3374d11
updated test_return_records_from_given_csv_file for Budget stream test
darynaishchenko Feb 21, 2024
a6d89c2
updated resource data
darynaishchenko Feb 26, 2024
5380892
added unittest for ioe case
darynaishchenko Feb 26, 2024
b8e683f
updated integration tests with state validation in request
darynaishchenko Feb 26, 2024
ca13f4f
updated test dates for monthly report
darynaishchenko Feb 27, 2024
7156617
Merge branch 'master' into daryna/source-bing-ads/stream-budget-and-p…
darynaishchenko Feb 27, 2024
f55b223
updated vesrion in pyproject.toml
darynaishchenko Feb 27, 2024
ec0a696
test stream budget: fix date for incremental sync
darynaishchenko Feb 29, 2024
5a29581
budget and product: updated cat config
darynaishchenko Feb 29, 2024
aaad088
updated budget schema
darynaishchenko Feb 29, 2024
df4c4f8
Merge branch 'master' into daryna/source-bing-ads/stream-budget-and-p…
darynaishchenko Feb 29, 2024
66a0cc5
Merge branch 'master' into daryna/source-bing-ads/stream-budget-and-p…
darynaishchenko Mar 1, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading