From 472556356bda7eae05d538216a26ede68172016c Mon Sep 17 00:00:00 2001 From: Josh Lloyd Date: Thu, 24 Mar 2022 14:37:54 -0600 Subject: [PATCH 01/11] added more fields to the campaign stream --- tap_googleads/schemas/campaign.json | 108 +++++++++++++++++++++++----- tap_googleads/streams.py | 27 ++++++- 2 files changed, 116 insertions(+), 19 deletions(-) diff --git a/tap_googleads/schemas/campaign.json b/tap_googleads/schemas/campaign.json index e0d0f39..aae6db4 100644 --- a/tap_googleads/schemas/campaign.json +++ b/tap_googleads/schemas/campaign.json @@ -1,22 +1,94 @@ { - "type": "object", - "properties": { - "_sdc_primary_key": { - "type": "string" - }, - "campaign": { - "type": "object", - "properties": { - "resourceName": { - "type": "string" - }, - "name": { - "type": "string" - }, - "id": { - "type": "string" - } - } + "type": "object", + "properties": { + "_sdc_primary_key": { + "type": "string" + }, + "campaign": { + "type": "object", + "properties": { + "resourceName": { + "type": "string" + }, + "name": { + "type": "string" + }, + "id": { + "type": "string" + }, + "status": { + "type": "string" + }, + "accessibleBiddingStrategy": { + "type": "string" + }, + "adServingOptimizationStatus": { + "type": "string" + }, + "advertisingChannelSubType": { + "type": "string" + }, + "advertisingChannelType": { + "type": "string" + }, + "baseCampaign": { + "type": "string" + }, + "biddingStrategy": { + "type": "string" + }, + "biddingStrategyType": { + "type": "string" + }, + "campaignBudget": { + "type": "string" + }, + "endDate": { + "type": "string" + }, + "excludedParentAssetFieldTypes": { + "type": "array" + }, + "experimentType": { + "type": "string" + }, + "finalUrlSuffix": { + "type": "string" + }, + "frequencyCaps": { + "type": "array" + }, + "labels": { + "type": "array" + }, + "paymentMode": { + "type": "string" + }, + "servingStatus": { + "type": "string" + }, + "startDate": { + "type": "string" + }, + "trackingUrlTemplate": { + "type": "string" + }, + "urlCustomParameters": { + "type": "array" + }, + "videoBrandSafetySuitability": { + "type": "string" + }, + "manualCpm": { + "type": "object" + }, + "manualCpv": { + "type": "object" + }, + "targetCpm": { + "type": "object" } + } } + } } diff --git a/tap_googleads/streams.py b/tap_googleads/streams.py index eacbf26..b6fde1b 100644 --- a/tap_googleads/streams.py +++ b/tap_googleads/streams.py @@ -194,7 +194,32 @@ def gaql(self): return """ SELECT campaign.id , campaign.name - FROM campaign + , campaign.accessible_bidding_strategy + , campaign.ad_serving_optimization_status + , campaign.advertising_channel_sub_type + , campaign.advertising_channel_type + , campaign.base_campaign + , campaign.bidding_strategy + , campaign.bidding_strategy_type + , campaign.campaign_budget + , campaign.end_date + , campaign.excluded_parent_asset_field_types + , campaign.experiment_type + , campaign.final_url_suffix + , campaign.frequency_caps + , campaign.labels + , campaign.manual_cpm + , campaign.manual_cpv + , campaign.payment_mode + , campaign.resource_name + , campaign.serving_status + , campaign.start_date + , campaign.status + , campaign.target_cpm + , campaign.tracking_url_template + , campaign.url_custom_parameters + , campaign.video_brand_safety_suitability + FROM campaign ORDER BY campaign.id """ From 6acb2cab8c7dc040b0fc000a1e808c871550beee Mon Sep 17 00:00:00 2001 From: Josh Lloyd Date: Thu, 24 Mar 2022 15:20:31 -0600 Subject: [PATCH 02/11] initial crack --- meltano.yml | 7 +++++++ tap_googleads/streams.py | 14 ++++++++++++-- tap_googleads/tap.py | 12 ++++++++++++ 3 files changed, 31 insertions(+), 2 deletions(-) diff --git a/meltano.yml b/meltano.yml index 0781a48..94c6f6f 100644 --- a/meltano.yml +++ b/meltano.yml @@ -22,6 +22,13 @@ plugins: kind: password - name: login_customer_id kind: password + - name: start_date + kind: string + - name: end_date + kind: string + config: + start_date: 2022-03-23 + end_date: 2022-03-24 loaders: - name: target-jsonl variant: andyh1203 diff --git a/tap_googleads/streams.py b/tap_googleads/streams.py index b6fde1b..6f4b6d9 100644 --- a/tap_googleads/streams.py +++ b/tap_googleads/streams.py @@ -300,7 +300,17 @@ class AdGroupsPerformance(ReportsStream): class CampaignPerformance(ReportsStream): """Campaign Performance""" - gaql = """ + @property + def start_date(self): + return self.config.get("start_date") or "2022-01-01" + + @property + def end_date(self): + return self.config.get("end_date") or "2022-01-02" + + @property + def gaql(self): + return f""" SELECT campaign.id , campaign.name , campaign.status @@ -312,7 +322,7 @@ class CampaignPerformance(ReportsStream): , metrics.average_cpc , metrics.cost_micros FROM campaign - WHERE segments.date DURING LAST_7_DAYS + WHERE segments.date BETWEEN {self.start_date} AND {self.end_date} """ records_jsonpath = "$.results[*]" name = "campaign_performance" diff --git a/tap_googleads/tap.py b/tap_googleads/tap.py index 2a9307f..f6c6165 100644 --- a/tap_googleads/tap.py +++ b/tap_googleads/tap.py @@ -73,6 +73,18 @@ class TapGoogleAds(Tap): th.StringType, required=True, ), + th.Property( + "start_date", + th.StringType, + required=False, + default="", + ), + th.Property( + "end_date", + th.StringType, + required=False, + default="", + ), ).to_dict() def discover_streams(self) -> List[Stream]: From 597dd5c6c8337fc82d1b7d0aa7a40f5b378a8150 Mon Sep 17 00:00:00 2001 From: Josh Lloyd Date: Thu, 24 Mar 2022 16:04:15 -0600 Subject: [PATCH 03/11] added capability of selecting a date range for applicable streams --- meltano.yml | 3 --- tap_googleads/streams.py | 47 ++++++++++++++++++++++++---------------- tap_googleads/tap.py | 5 +++-- 3 files changed, 31 insertions(+), 24 deletions(-) diff --git a/meltano.yml b/meltano.yml index 94c6f6f..d5bd96b 100644 --- a/meltano.yml +++ b/meltano.yml @@ -26,9 +26,6 @@ plugins: kind: string - name: end_date kind: string - config: - start_date: 2022-03-23 - end_date: 2022-03-24 loaders: - name: target-jsonl variant: andyh1203 diff --git a/tap_googleads/streams.py b/tap_googleads/streams.py index 626b5c5..19cd657 100644 --- a/tap_googleads/streams.py +++ b/tap_googleads/streams.py @@ -278,7 +278,9 @@ def gaql(self): class AdGroupsPerformance(ReportsStream): """AdGroups Performance""" - gaql = """ + @property + def gaql(self): + return f""" SELECT campaign.id , ad_group.id , metrics.impressions @@ -286,7 +288,8 @@ class AdGroupsPerformance(ReportsStream): , metrics.cost_micros , segments.date FROM ad_group - WHERE segments.date DURING LAST_7_DAYS + WHERE segments.date BETWEEN '{self.config["start_date"]}' + AND '{self.config["end_date"]}' """ records_jsonpath = "$.results[*]" @@ -300,14 +303,6 @@ class AdGroupsPerformance(ReportsStream): class CampaignPerformance(ReportsStream): """Campaign Performance""" - @property - def start_date(self): - return self.config.get("start_date") or "2022-01-01" - - @property - def end_date(self): - return self.config.get("end_date") or "2022-01-02" - @property def gaql(self): return f""" @@ -322,8 +317,10 @@ def gaql(self): , metrics.average_cpc , metrics.cost_micros FROM campaign - WHERE segments.date BETWEEN {self.start_date} AND {self.end_date} + WHERE segments.date BETWEEN '{self.config["start_date"]}' + AND '{self.config["end_date"]}' """ + records_jsonpath = "$.results[*]" name = "campaign_performance" primary_keys_jsonpaths = ["campaign.resourceName", "segments.date"] @@ -335,7 +332,9 @@ def gaql(self): class CampaignPerformanceByAgeRangeAndDevice(ReportsStream): """Campaign Performance By Age Range and Device""" - gaql = """ + @property + def gaql(self): + return f""" SELECT ad_group_criterion.age_range.type , campaign.name , campaign.id @@ -353,7 +352,8 @@ class CampaignPerformanceByAgeRangeAndDevice(ReportsStream): , metrics.cost_micros , campaign.advertising_channel_type FROM age_range_view - WHERE segments.date DURING LAST_7_DAYS + WHERE segments.date BETWEEN '{self.config["start_date"]}' + AND '{self.config["end_date"]}' """ records_jsonpath = "$.results[*]" @@ -373,7 +373,9 @@ class CampaignPerformanceByAgeRangeAndDevice(ReportsStream): class CampaignPerformanceByGenderAndDevice(ReportsStream): """Campaign Performance By Age Range and Device""" - gaql = """ + @property + def gaql(self): + return f""" SELECT ad_group_criterion.gender.type , campaign.name , campaign.status @@ -391,7 +393,8 @@ class CampaignPerformanceByGenderAndDevice(ReportsStream): , metrics.cost_micros , campaign.advertising_channel_type FROM gender_view - WHERE segments.date DURING LAST_7_DAYS + WHERE segments.date BETWEEN '{self.config["start_date"]}' + AND '{self.config["end_date"]}' """ records_jsonpath = "$.results[*]" @@ -411,7 +414,9 @@ class CampaignPerformanceByGenderAndDevice(ReportsStream): class CampaignPerformanceByLocation(ReportsStream): """Campaign Performance By Age Range and Device""" - gaql = """ + @property + def gaql(self): + return f""" SELECT campaign_criterion.location.geo_target_constant , campaign.name , campaign.id @@ -423,7 +428,8 @@ class CampaignPerformanceByLocation(ReportsStream): , metrics.average_cpc , metrics.cost_micros FROM location_view - WHERE segments.date DURING LAST_7_DAYS + WHERE segments.date BETWEEN '{self.config["start_date"]}' + AND '{self.config["end_date"]}' AND campaign_criterion.status != 'REMOVED' """ @@ -442,7 +448,9 @@ class CampaignPerformanceByLocation(ReportsStream): class ConversionsByLocation(ReportsStream): """Conversions By Location""" - gaql = """ + @property + def gaql(self): + return f""" SELECT campaign_criterion.location.geo_target_constant , campaign.name , campaign.id @@ -451,7 +459,8 @@ class ConversionsByLocation(ReportsStream): , segments.conversion_action_category , metrics.conversions FROM location_view - WHERE segments.date DURING LAST_7_DAYS + WHERE segments.date BETWEEN '{self.config["start_date"]}' + AND '{self.config["end_date"]}' AND campaign_criterion.status != 'REMOVED' """ diff --git a/tap_googleads/tap.py b/tap_googleads/tap.py index f6c6165..4455d84 100644 --- a/tap_googleads/tap.py +++ b/tap_googleads/tap.py @@ -1,5 +1,6 @@ """GoogleAds tap class.""" +import datetime from typing import List from singer_sdk import Tap, Stream @@ -77,13 +78,13 @@ class TapGoogleAds(Tap): "start_date", th.StringType, required=False, - default="", + default=datetime.date.today().isoformat(), ), th.Property( "end_date", th.StringType, required=False, - default="", + default=datetime.date.today().isoformat(), ), ).to_dict() From bcf96f666c513040a771632fbf551a78d0c95685 Mon Sep 17 00:00:00 2001 From: Josh Lloyd Date: Tue, 12 Jul 2022 12:56:23 -0600 Subject: [PATCH 04/11] fixed 400 bad path error --- tap_googleads/client.py | 2 +- tap_googleads/tests/test_customer_not_found.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tap_googleads/client.py b/tap_googleads/client.py index 1333969..71cfaba 100644 --- a/tap_googleads/client.py +++ b/tap_googleads/client.py @@ -20,7 +20,7 @@ class GoogleAdsStream(RESTStream): """GoogleAds stream class.""" - url_base = "https://googleads.googleapis.com/v8" + url_base = "https://googleads.googleapis.com/v11" records_jsonpath = "$[*]" # Or override `parse_response`. next_page_token_jsonpath = "$.nextPageToken" # Or override `get_next_page_token`. diff --git a/tap_googleads/tests/test_customer_not_found.py b/tap_googleads/tests/test_customer_not_found.py index f3b7457..7a121d1 100644 --- a/tap_googleads/tests/test_customer_not_found.py +++ b/tap_googleads/tests/test_customer_not_found.py @@ -69,7 +69,7 @@ def test_customer_not_enabled(mocked_responses): mocked_responses.add( responses.POST, # TODO cleanup long url, googleads.googleapis.com/* would suffice - "https://googleads.googleapis.com/v8/customers/12345/googleAds:search?pageSize=10000&query=%0A%20%20%20%20%20%20%20%20SELECT%20campaign.id,%20campaign.name%20FROM%20campaign%20ORDER%20BY%20campaign.id%0A%20%20%20%20%20%20%20%20", + "https://googleads.googleapis.com/v11/customers/12345/googleAds:search?pageSize=10000&query=%0A%20%20%20%20%20%20%20%20SELECT%20campaign.id,%20campaign.name%20FROM%20campaign%20ORDER%20BY%20campaign.id%0A%20%20%20%20%20%20%20%20", body=json.dumps(customer_not_enabled_body).encode("utf-8"), status=403, content_type="application/json", From 3686b4bc1708f5eb70dac410859d4207f3e24e4b Mon Sep 17 00:00:00 2001 From: Josh Lloyd Date: Tue, 12 Jul 2022 13:20:17 -0600 Subject: [PATCH 05/11] clarified readme instructions on getting refresh token --- README.md | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index faed132..7ac5988 100644 --- a/README.md +++ b/README.md @@ -18,9 +18,25 @@ pipx install tap-googleads ## Configuration ### Get refresh token -1. GET https://accounts.google.com/o/oauth2/v2/auth?response_type=code&client_id=client_id&redirect_uri=http://127.0.0.1&scope=https://www.googleapis.com/auth/adwords&state=autoidm&access_type=offline&prompt=select_account&include_granted_scopes=true -1. POST https://www.googleapis.com/oauth2/v4/token?code={code}&client_id={client_id}&client_secret={client_secret}&redirect_uri=http://127.0.0.1&grant_type=authorization_code -1. POST https://www.googleapis.com/oauth2/v4/token?refresh_token={refres_token}&client_id={client_id}&client_secret={client_secret]&grant_type=refresh_token +Get a developer token, client id, and client secret as recommended in +the [Google Ads API documentation](https://developers.google.com/google-ads/api/docs/first-call/overview). +Then do the following: + +1. Modify following template url and put it in a browser. Then follow the prompts to authenticate. +`GET https://accounts.google.com/o/oauth2/v2/auth?response_type=code&client_id={client_id}&redirect_uri=http://127.0.0.1&scope=https://www.googleapis.com/auth/adwords&access_type=offline&prompt=select_account&include_granted_scopes=true` + + +2. Modify the following url with the value in the `code` parameter that was returned in the previous browser url bar. Replace all other templated values and submit a `POST` request: +`https://www.googleapis.com/oauth2/v4/token?code={code}&client_id={client_id}&client_secret={client_secret}&redirect_uri=http://127.0.0.1&grant_type=authorization_code` + + +3. From the response you can grab the `refresh_token` and use it as is. Sometimes the following step is also required. + + +4. (IF NECESSARY) Modify the following templated url as suggested and submit a POST request. +`https://www.googleapis.com/oauth2/v4/token?refresh_token={refres_token}&client_id={client_id}&client_secret={client_secret]&grant_type=refresh_token` + + ### Accepted Config Options - [ ] `Developer TODO:` Provide a list of config options accepted by the tap. From f8248ec871b2423ac5849272f0cef303946bbbf5 Mon Sep 17 00:00:00 2001 From: Josh Lloyd Date: Tue, 12 Jul 2022 14:06:22 -0600 Subject: [PATCH 06/11] added the customers stream back in --- tap_googleads/streams.py | 13 +++++++++++++ tap_googleads/tap.py | 2 ++ 2 files changed, 15 insertions(+) diff --git a/tap_googleads/streams.py b/tap_googleads/streams.py index ef0f016..69e42b5 100644 --- a/tap_googleads/streams.py +++ b/tap_googleads/streams.py @@ -12,6 +12,19 @@ SCHEMAS_DIR = Path(__file__).parent / Path("./schemas") +class CustomerStream(GoogleAdsStream): + """Define custom stream.""" + + @property + def path(self): + return "/customers/" + self.config["customer_id"] + + name = "customers" + primary_keys = ["id"] + replication_key = None + schema_filepath = SCHEMAS_DIR / "customer.json" + + class AccessibleCustomers(GoogleAdsStream): """Accessible Customers""" diff --git a/tap_googleads/tap.py b/tap_googleads/tap.py index 4599f10..1fd7887 100644 --- a/tap_googleads/tap.py +++ b/tap_googleads/tap.py @@ -9,6 +9,7 @@ from tap_googleads.streams import ( CampaignsStream, + CustomerStream, AdGroupsStream, AdGroupsPerformance, AccessibleCustomers, @@ -24,6 +25,7 @@ STREAM_TYPES = [ CampaignsStream, + CustomerStream, AdGroupsStream, AdGroupsPerformance, AccessibleCustomers, From 00cfd9e1df2224bbd61f254cb500f08108ba7a1f Mon Sep 17 00:00:00 2001 From: Josh Lloyd Date: Tue, 12 Jul 2022 14:33:21 -0600 Subject: [PATCH 07/11] removed duplicate start and end date properties --- tap_googleads/tap.py | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/tap_googleads/tap.py b/tap_googleads/tap.py index 1fd7887..8b0efc4 100644 --- a/tap_googleads/tap.py +++ b/tap_googleads/tap.py @@ -97,18 +97,6 @@ class TapGoogleAds(Tap): required=True, description="Date to end our search on, applies to Streams where there is a filter date. Note that the query is BETWEEN start_date AND end_date", ), - th.Property( - "start_date", - th.StringType, - required=False, - default=datetime.date.today().isoformat(), - ), - th.Property( - "end_date", - th.StringType, - required=False, - default=datetime.date.today().isoformat(), - ), ).to_dict() def discover_streams(self) -> List[Stream]: From 17980cb2449d1971892ed3e3e7dfbc95a0ce554a Mon Sep 17 00:00:00 2001 From: Josh Lloyd Date: Tue, 12 Jul 2022 14:34:52 -0600 Subject: [PATCH 08/11] removed extra datetime import --- tap_googleads/tap.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tap_googleads/tap.py b/tap_googleads/tap.py index 8b0efc4..478cc89 100644 --- a/tap_googleads/tap.py +++ b/tap_googleads/tap.py @@ -1,6 +1,5 @@ """GoogleAds tap class.""" -import datetime from typing import List from singer_sdk import Tap, Stream From feed1ebd02e391517249db1fdb2f01be633cffa6 Mon Sep 17 00:00:00 2001 From: Josh Lloyd Date: Thu, 18 Aug 2022 15:10:27 -0600 Subject: [PATCH 09/11] fixed the test_customer_not_enabled --- tap_googleads/tests/test_customer_not_found.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tap_googleads/tests/test_customer_not_found.py b/tap_googleads/tests/test_customer_not_found.py index cbc12f9..e1657ac 100644 --- a/tap_googleads/tests/test_customer_not_found.py +++ b/tap_googleads/tests/test_customer_not_found.py @@ -69,7 +69,7 @@ def test_customer_not_enabled(mocked_responses): mocked_responses.add( responses.POST, # TODO cleanup long url, googleads.googleapis.com/* would suffice - "https://googleads.googleapis.com/v11/customers/12345/googleAds:search?pageSize=10000&query=%0A%20%20%20%20%20%20%20%20%20%20%20%20SELECT%20campaign.id%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20,%20campaign.name%0A%20%20%20%20%20%20%20%20%20%20%20%20FROM%20campaign%20%0A%20%20%20%20%20%20%20%20%20%20%20%20ORDER%20BY%20campaign.id%0A%20%20%20%20%20%20%20%20", + "https://googleads.googleapis.com/v11/customers/12345/googleAds:search?pageSize=10000&query=%0A%20%20%20%20%20%20%20%20%20%20%20%20SELECT%20campaign.id%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20,%20campaign.name%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20,%20campaign.accessible_bidding_strategy%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20,%20campaign.ad_serving_optimization_status%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20,%20campaign.advertising_channel_sub_type%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20,%20campaign.advertising_channel_type%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20,%20campaign.base_campaign%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20,%20campaign.bidding_strategy%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20,%20campaign.bidding_strategy_type%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20,%20campaign.campaign_budget%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20,%20campaign.end_date%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20,%20campaign.excluded_parent_asset_field_types%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20,%20campaign.experiment_type%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20,%20campaign.final_url_suffix%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20,%20campaign.frequency_caps%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20,%20campaign.labels%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20,%20campaign.manual_cpm%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20,%20campaign.manual_cpv%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20,%20campaign.payment_mode%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20,%20campaign.resource_name%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20,%20campaign.serving_status%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20,%20campaign.start_date%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20,%20campaign.status%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20,%20campaign.target_cpm%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20,%20campaign.tracking_url_template%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20,%20campaign.url_custom_parameters%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20,%20campaign.video_brand_safety_suitability%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20FROM%20campaign%20%0A%20%20%20%20%20%20%20%20%20%20%20%20ORDER%20BY%20campaign.id%0A%20%20%20%20%20%20%20%20", body=json.dumps(customer_not_enabled_body).encode("utf-8"), status=403, content_type="application/json", From 5faacac21632fa251957ba31fd8261e95060c08e Mon Sep 17 00:00:00 2001 From: Josh Lloyd Date: Thu, 8 Sep 2022 09:24:38 -0600 Subject: [PATCH 10/11] added missing primary key to campaing_performance and conversions_by_location streams --- tap_googleads/streams.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/tap_googleads/streams.py b/tap_googleads/streams.py index 69e42b5..006a653 100644 --- a/tap_googleads/streams.py +++ b/tap_googleads/streams.py @@ -342,7 +342,11 @@ def gaql(self) -> str: records_jsonpath = "$.results[*]" name = "campaign_performance" - primary_keys_jsonpaths = ["campaign.resourceName", "segments.date"] + primary_keys_jsonpaths = [ + "campaign.resourceName", + "segments.date", + "segments.device", + ] primary_keys = ["_sdc_primary_key"] replication_key = None schema_filepath = SCHEMAS_DIR / "campaign_performance.json" @@ -485,6 +489,7 @@ def gaql(self) -> str: "campaign.resourceName", "locationView.resourceName", "segments.date", + "segments.conversion_action_category", ] primary_keys = ["_sdc_primary_key"] replication_key = None From 7c5daa42dab6b97146f7e59efda8574e443d1aed Mon Sep 17 00:00:00 2001 From: Josh Lloyd Date: Tue, 4 Apr 2023 09:46:47 -0600 Subject: [PATCH 11/11] updated api version --- tap_googleads/client.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tap_googleads/client.py b/tap_googleads/client.py index 20c85c2..c84d0e2 100644 --- a/tap_googleads/client.py +++ b/tap_googleads/client.py @@ -20,7 +20,7 @@ class GoogleAdsStream(RESTStream): """GoogleAds stream class.""" - url_base = "https://googleads.googleapis.com/v11" + url_base = "https://googleads.googleapis.com/v12" records_jsonpath = "$[*]" # Or override `parse_response`. next_page_token_jsonpath = "$.nextPageToken" # Or override `get_next_page_token`.