diff --git a/airbyte-config/init/src/main/resources/seed/source_definitions.yaml b/airbyte-config/init/src/main/resources/seed/source_definitions.yaml index e77998c6131a7..249eab39bc993 100644 --- a/airbyte-config/init/src/main/resources/seed/source_definitions.yaml +++ b/airbyte-config/init/src/main/resources/seed/source_definitions.yaml @@ -311,7 +311,7 @@ - name: Google Ads sourceDefinitionId: 253487c0-2246-43ba-a21f-5116b20a2c50 dockerRepository: airbyte/source-google-ads - dockerImageTag: 0.1.37 + dockerImageTag: 0.1.38 documentationUrl: https://docs.airbyte.io/integrations/sources/google-ads icon: google-adwords.svg sourceType: api diff --git a/airbyte-config/init/src/main/resources/seed/source_specs.yaml b/airbyte-config/init/src/main/resources/seed/source_specs.yaml index 4d0669ed6655a..c62d64816b754 100644 --- a/airbyte-config/init/src/main/resources/seed/source_specs.yaml +++ b/airbyte-config/init/src/main/resources/seed/source_specs.yaml @@ -2688,7 +2688,7 @@ supportsNormalization: false supportsDBT: false supported_destination_sync_modes: [] -- dockerImage: "airbyte/source-google-ads:0.1.37" +- dockerImage: "airbyte/source-google-ads:0.1.38" spec: documentationUrl: "https://docs.airbyte.com/integrations/sources/google-ads" connectionSpecification: @@ -2715,6 +2715,7 @@ developer_token: type: "string" title: "Developer Token" + order: 0 description: "Developer token granted by Google to use their APIs. More\ \ instruction on how to find this value in our docs" @@ -2722,27 +2723,31 @@ client_id: type: "string" title: "Client ID" + order: 1 description: "The Client ID of your Google Ads developer application.\ \ More instruction on how to find this value in our docs" client_secret: type: "string" title: "Client Secret" + order: 2 description: "The Client Secret of your Google Ads developer application.\ \ More instruction on how to find this value in our docs" airbyte_secret: true - access_token: + refresh_token: type: "string" - title: "Access Token" - description: "Access Token for making authenticated requests. More instruction\ + title: "Refresh Token" + order: 3 + description: "The token for obtaining a new access token. More instruction\ \ on how to find this value in our docs" airbyte_secret: true - refresh_token: + access_token: type: "string" - title: "Refresh Token" - description: "The token for obtaining a new access token. More instruction\ + title: "Access Token (Optional)" + order: 4 + description: "Access Token for making authenticated requests. More instruction\ \ on how to find this value in our docs" airbyte_secret: true diff --git a/airbyte-integrations/connectors/source-google-ads/Dockerfile b/airbyte-integrations/connectors/source-google-ads/Dockerfile index 2bba65c96c907..28f344f56d961 100644 --- a/airbyte-integrations/connectors/source-google-ads/Dockerfile +++ b/airbyte-integrations/connectors/source-google-ads/Dockerfile @@ -13,5 +13,5 @@ COPY main.py ./ ENTRYPOINT ["python", "/airbyte/integration_code/main.py"] -LABEL io.airbyte.version=0.1.37 +LABEL io.airbyte.version=0.1.38 LABEL io.airbyte.name=airbyte/source-google-ads diff --git a/airbyte-integrations/connectors/source-google-ads/source_google_ads/spec.json b/airbyte-integrations/connectors/source-google-ads/source_google_ads/spec.json index c9b0c87b9253f..4dafd39b2826a 100644 --- a/airbyte-integrations/connectors/source-google-ads/source_google_ads/spec.json +++ b/airbyte-integrations/connectors/source-google-ads/source_google_ads/spec.json @@ -22,31 +22,36 @@ "developer_token": { "type": "string", "title": "Developer Token", + "order": 0, "description": "Developer token granted by Google to use their APIs. More instruction on how to find this value in our docs", "airbyte_secret": true }, "client_id": { "type": "string", "title": "Client ID", + "order": 1, "description": "The Client ID of your Google Ads developer application. More instruction on how to find this value in our docs" }, "client_secret": { "type": "string", "title": "Client Secret", + "order": 2, "description": "The Client Secret of your Google Ads developer application. More instruction on how to find this value in our docs", "airbyte_secret": true }, - "access_token": { - "type": "string", - "title": "Access Token", - "description": "Access Token for making authenticated requests. More instruction on how to find this value in our docs", - "airbyte_secret": true - }, "refresh_token": { "type": "string", "title": "Refresh Token", + "order": 3, "description": "The token for obtaining a new access token. More instruction on how to find this value in our docs", "airbyte_secret": true + }, + "access_token": { + "type": "string", + "title": "Access Token (Optional)", + "order": 4, + "description": "Access Token for making authenticated requests. More instruction on how to find this value in our docs", + "airbyte_secret": true } } }, diff --git a/airbyte-integrations/connectors/source-google-ads/unit_tests/conftest.py b/airbyte-integrations/connectors/source-google-ads/unit_tests/conftest.py index 8287466b91bb0..a04c473402e23 100644 --- a/airbyte-integrations/connectors/source-google-ads/unit_tests/conftest.py +++ b/airbyte-integrations/connectors/source-google-ads/unit_tests/conftest.py @@ -2,15 +2,43 @@ # Copyright (c) 2021 Airbyte, Inc., all rights reserved. # -import json - import pytest @pytest.fixture(scope="session", name="config") -def config_fixture(): - with open("secrets/config.json", "r") as config_file: - return json.load(config_file) +def test_config(): + config = { + "credentials": { + "developer_token": "test_token", + "client_id": "test_client_id", + "client_secret": "test_client_secret", + "refresh_token": "test_refresh_token", + }, + "customer_id": "123", + "start_date": "2021-01-01", + "conversion_window_days": 14, + "custom_queries": [ + { + "query": "SELECT campaign.accessible_bidding_strategy, segments.ad_destination_type, campaign.start_date, campaign.end_date FROM campaign", + "primary_key": None, + "cursor_field": "campaign.start_date", + "table_name": "happytable", + }, + { + "query": "SELECT segments.ad_destination_type, segments.ad_network_type, segments.day_of_week, customer.auto_tagging_enabled, customer.id, metrics.conversions, campaign.start_date FROM campaign", + "primary_key": "customer.id", + "cursor_field": None, + "table_name": "unhappytable", + }, + { + "query": "SELECT ad_group.targeting_setting.target_restrictions FROM ad_group", + "primary_key": "customer.id", + "cursor_field": None, + "table_name": "ad_group_custom", + }, + ], + } + return config @pytest.fixture(autouse=True) diff --git a/airbyte-integrations/connectors/source-google-ads/unit_tests/test_streams.py b/airbyte-integrations/connectors/source-google-ads/unit_tests/test_streams.py index 6099715203d53..bbd28a09b087c 100644 --- a/airbyte-integrations/connectors/source-google-ads/unit_tests/test_streams.py +++ b/airbyte-integrations/connectors/source-google-ads/unit_tests/test_streams.py @@ -16,26 +16,10 @@ from .common import MockGoogleAdsClient as MockGoogleAdsClient -@pytest.fixture(scope="module") -def test_config(): - config = { - "credentials": { - "developer_token": "test_token", - "client_id": "test_client_id", - "client_secret": "test_client_secret", - "refresh_token": "test_refresh_token", - }, - "customer_id": "123", - "start_date": "2021-01-01", - "conversion_window_days": 14, - } - return config - - @pytest.fixture -def mock_ads_client(mocker): +def mock_ads_client(mocker, config): """Mock google ads library method, so it returns mocked Client""" - mocker.patch("source_google_ads.google_ads.GoogleAdsClient.load_from_dict", return_value=MockGoogleAdsClient(test_config)) + mocker.patch("source_google_ads.google_ads.GoogleAdsClient.load_from_dict", return_value=MockGoogleAdsClient(config)) # EXPIRED_PAGE_TOKEN exception will be raised when page token has expired. @@ -81,7 +65,7 @@ def send_request(self, query: str, customer_id: str): return mock_response_2() -def test_page_token_expired_retry_succeeds(mock_ads_client, test_config): +def test_page_token_expired_retry_succeeds(mock_ads_client, config): """ Page token expired while reading records on date 2021-01-03 The latest read record is {"segments.date": "2021-01-03", "click_view.gclid": "4"} @@ -90,11 +74,11 @@ def test_page_token_expired_retry_succeeds(mock_ads_client, test_config): """ stream_slice = {"start_date": "2021-01-01", "end_date": "2021-01-15"} - google_api = MockGoogleAds(credentials=test_config["credentials"], customer_id=test_config["customer_id"]) + google_api = MockGoogleAds(credentials=config["credentials"], customer_id=config["customer_id"]) incremental_stream_config = dict( api=google_api, - conversion_window_days=test_config["conversion_window_days"], - start_date=test_config["start_date"], + conversion_window_days=config["conversion_window_days"], + start_date=config["start_date"], time_zone="local", end_date="2021-04-04", ) @@ -139,18 +123,18 @@ def send_request(self, query: str, customer_id: str): return mock_response_fails_2() -def test_page_token_expired_retry_fails(mock_ads_client, test_config): +def test_page_token_expired_retry_fails(mock_ads_client, config): """ Page token has expired while reading records within date "2021-01-03", it should raise error, because Google Ads API doesn't allow filter by datetime. """ stream_slice = {"start_date": "2021-01-01", "end_date": "2021-01-15"} - google_api = MockGoogleAdsFails(credentials=test_config["credentials"], customer_id=test_config["customer_id"]) + google_api = MockGoogleAdsFails(credentials=config["credentials"], customer_id=config["customer_id"]) incremental_stream_config = dict( api=google_api, - conversion_window_days=test_config["conversion_window_days"], - start_date=test_config["start_date"], + conversion_window_days=config["conversion_window_days"], + start_date=config["start_date"], time_zone="local", end_date="2021-04-04", ) @@ -181,7 +165,7 @@ def send_request(self, query: str, customer_id: str): return mock_response_fails_one_date() -def test_page_token_expired_it_should_fail_date_range_1_day(mock_ads_client, test_config): +def test_page_token_expired_it_should_fail_date_range_1_day(mock_ads_client, config): """ Page token has expired while reading records within date "2021-01-03", it should raise error, because Google Ads API doesn't allow filter by datetime. @@ -189,11 +173,11 @@ def test_page_token_expired_it_should_fail_date_range_1_day(mock_ads_client, tes """ stream_slice = {"start_date": "2021-01-03", "end_date": "2021-01-04"} - google_api = MockGoogleAdsFailsOneDate(credentials=test_config["credentials"], customer_id=test_config["customer_id"]) + google_api = MockGoogleAdsFailsOneDate(credentials=config["credentials"], customer_id=config["customer_id"]) incremental_stream_config = dict( api=google_api, - conversion_window_days=test_config["conversion_window_days"], - start_date=test_config["start_date"], + conversion_window_days=config["conversion_window_days"], + start_date=config["start_date"], time_zone="local", end_date="2021-04-04", ) diff --git a/docs/integrations/sources/google-ads.md b/docs/integrations/sources/google-ads.md index d038f0023c142..881ee35690d0b 100644 --- a/docs/integrations/sources/google-ads.md +++ b/docs/integrations/sources/google-ads.md @@ -1,114 +1,126 @@ # Google Ads -:::caution +This page contains the setup guide and reference information for the Google Ads source connector. -If you don't already have a developer token from Google Ads, make sure you follow the [instructions](google-ads.md#how-to-apply-for-the-developer-token) so your request doesn't get denied. +## Prerequisites -::: +Google Ads registered account with +* Customer ID +* Login Customer ID (you can find more information about this field in [Google Ads docs](https://developers.google.com/google-ads/api/docs/concepts/call-structure#cid)) +* Custom GAQL Queries (if needed) -## Features +Also: +* Start Date +* End Date +* Conversion Window -| Feature | Supported? | -| :---------------------------- | :--------- | -| Full Refresh Sync | Yes | -| Incremental Sync | Yes | -| Replicate Incremental Deletes | No | -| SSL connection | Yes | +For Airbyte OSS: +Google Ads Account with an approved Developer Token. (note: In order to get API access to Google Ads, you must have a "manager" account; standard accounts cannot generate a Developer Token. This manager account must be created separately from your standard account. You can find more information about this distinction in the [Google Ads docs](https://support.google.com/google-ads/answer/6139186).) +You'll also need to find these values. See the [setup guide](#setup-guide) for instructions. -## Supported Tables +* Client ID +* Client Secret +* Refresh Token -This source is capable of syncing the following tables and their data: +## Setup guide +### Step 1: Set up Google Ads -### Main Tables +This guide will provide information as if starting from scratch. Please skip over any steps you have already completed. -- [accounts](https://developers.google.com/google-ads/api/fields/v8/customer) -- [ad_group_ads](https://developers.google.com/google-ads/api/fields/v8/ad_group_ad) -- [ad_group_ad_labels](https://developers.google.com/google-ads/api/fields/v8/ad_group_ad_label) -- [ad_groups](https://developers.google.com/google-ads/api/fields/v8/ad_group) -- [ad_group_labels](https://developers.google.com/google-ads/api/fields/v8/ad_group_label) -- [campaigns](https://developers.google.com/google-ads/api/fields/v8/campaign) -- [campaign_labels](https://developers.google.com/google-ads/api/fields/v8/campaign_label) -- [click_view](https://developers.google.com/google-ads/api/reference/rpc/v8/ClickView) -- [keyword](https://developers.google.com/google-ads/api/fields/v8/keyword_view) -- [geographic](https://developers.google.com/google-ads/api/fields/v8/geographic_view) +1. Create a Google Ads Account. Here are [Google's instructions](https://support.google.com/google-ads/answer/6366720) on how to create one. +2. Create a Google Ads MANAGER Account. Here are [Google's instructions](https://ads.google.com/home/tools/manager-accounts/) on how to create one. +3. You should now have two Google Ads accounts: a normal account and a manager account. Link the Manager account to the normal account following [Google's documentation](https://support.google.com/google-ads/answer/7459601). +4. Select your `customer_id`. The `customer_id` refers to the id of each of your Google Ads accounts. This is the 10 digit number in the top corner of the page when you are in Google Ads UI. The source will only pull data from the accounts for which you provide an id. If you are having trouble finding it, check out [Google's instructions](https://support.google.com/google-ads/answer/1704344). -Note that `ad_groups`, `ad_group_ads`, and `campaigns` contain a `labels` field, which should be joined against their respective `*_labels` streams if you want to view the actual labels. For example, the `ad_groups` stream contains an `ad_group.labels` field, which you would join against the `ad_group_labels` stream's `label.resource_name` field. + ### Airbyte Open Source additional setup steps + 1. Apply for a developer token (**make sure you follow our** [**instructions**](google-ads.md#how-to-apply-for-the-developer-token) on your Manager account. This token allows you to access your data from the Google Ads API. Here are [Google's instructions](https://developers.google.com/google-ads/api/docs/first-call/dev-token). The docs are a little unclear on this point, but you will _not_ be able to access your data via the Google Ads API until this token is approved. You cannot use a test developer token, it has to be at least a basic developer token. It usually takes Google 24 hours to respond to these applications. This developer token is the value you will use in the `developer_token` field. + 2. Fetch your `client_id`, `client_secret`, and `refresh_token`. Google provides [instructions](https://developers.google.com/google-ads/api/docs/first-call/overview) on how to do this. -### Report Tables + ### How to apply for the developer token + Google is very picky about which software and which use case can get access to a developer token. The Airbyte team has worked with the Google Ads team to whitelist Airbyte and make sure you can get one (see [issue 1981](https://github.com/airbytehq/airbyte/issues/1981) for more information). + When you apply for a token, you need to mention: -- [account_performance_report](https://developers.google.com/google-ads/api/docs/migration/mapping#account_performance) -- [ad_group_ad_report](https://developers.google.com/google-ads/api/docs/migration/mapping#ad_performance) -- [display_keyword_report](https://developers.google.com/google-ads/api/docs/migration/mapping#display_keyword_performance) -- [display_topics_report](https://developers.google.com/google-ads/api/docs/migration/mapping#display_topics_performance) -- [shopping_performance_report](https://developers.google.com/google-ads/api/docs/migration/mapping#shopping_performance) -- [user_location_report](https://developers.google.com/google-ads/api/fields/v8/user_location_view) - -**Note**: Due to constraints from the Google Ads API, the `click_view` stream retrieves data one day at a time and can only retrieve data newer than 90 days ago + - Why you need the token (eg: want to run some internal analytics...) + - That you will be using the Airbyte Open Source project + - That you have full access to the code base (because we're open source) + - That you have full access to the server running the code (because you're self-hosting Airbyte) -**Note**: Due to constraints from the Google Ads API, [metrics](https://developers.google.com/google-ads/api/fields/v8/metrics) cannot be requested for a manager account. Therefore, report streams are only available when pulling data from a non-manager account. +## Step 2: Set up the Google Ads connector in Airbyte -**Note**: For incremental streams data is synced up to the previous day using your Google Ads account time zone. The reason is that Google Ads can filter data only by [date](https://developers.google.com/google-ads/api/fields/v8/ad_group_ad#segments.date) without time. Also, some report cannot load data in real time due to Google Ads [limitations](https://support.google.com/google-ads/answer/2544985?hl=en). +### For Airbyte Cloud: -## Getting Started \(Airbyte-Cloud\) +1. [Log into your Airbyte Cloud](https://cloud.airbyte.io/workspaces) account. +2. In the left navigation bar, click **Sources**. In the top-right corner, click **+new source**. +3. On the Set up the source page, enter the name for the Google Ads connector and select **Google Ads** from the Source type dropdown. +4. Click `Authenticate your Google Ads account` to sign in with Google and authorize your account. +5. Get the customer ID for your account. Learn how to do that [here](https://support.google.com/google-ads/answer/1704344) +6. If your access to the account is through a manager account, get the customer ID of the manager account. +7. Fill out a start date, and optionally, a conversion window, and custom [GAQL](https://developers.google.com/google-ads/api/docs/query/overview). +8. You're done. -1. Click `Authenticate your Google Ads account` to sign in with Google and authorize your account. +### For Airbyte OSS: +1. Create a new Google Ads source with a suitable name. 2. Get the customer ID for your account. Learn how to do that [here](https://support.google.com/google-ads/answer/1704344) 3. If your access to the account is through a manager account, get the customer ID of the manager account. -4. Fill out a start date, and optionally, a conversion window, and custom [GAQL](https://developers.google.com/google-ads/api/docs/query/overview). -5. You're done. +4. Fill out a start date, and optionally, end date and a conversion window, and custom [GAQL](https://developers.google.com/google-ads/api/docs/query/overview). +5. Fill out the Client ID, Client Secret, Access Token(if any), Refresh Token and the Developer Token from [Step 1](#step-1-set-up-google-ads)) +6. You're done -## Getting Started \(Airbyte Open-Source\) +## Supported sync modes -### Requirements +The Google Ads source connector supports the following[ sync modes](https://docs.airbyte.com/cloud/core-concepts#connection-sync-modes): + - Full Refresh | Overwrite + - Full Refresh | Append + - Incremental Sync | Append + - Incremental Sync | Deduped History -Google Ads Account with an approved Developer Token. \(note: In order to get API access to Google Ads, you must have a "manager" account; standard accounts cannot generate a Developer Token. This manager account must be created separately from your standard account. You can find more information about this distinction in the [Google Ads docs](https://support.google.com/google-ads/answer/6139186).\) +## Supported Streams -You'll need to find these values. See the [setup guide](#setup-guide) for instructions. - -- developer_token -- client_id -- client_secret -- refresh_token -- start_date -- customer_id -- login_customer_id \(you can find more information about this field in [Google Ads docs](https://developers.google.com/google-ads/api/docs/concepts/call-structure#cid)\) +This source is capable of syncing the following tables and their data: -### Setup guide +### Main Tables -This guide will provide information as if starting from scratch. Please skip over any steps you have already completed. +- [accounts](https://developers.google.com/google-ads/api/fields/v9/customer) +- [ad_group_ads](https://developers.google.com/google-ads/api/fields/v9/ad_group_ad) +- [ad_group_ad_labels](https://developers.google.com/google-ads/api/fields/v9/ad_group_ad_label) +- [ad_groups](https://developers.google.com/google-ads/api/fields/v9/ad_group) +- [ad_group_labels](https://developers.google.com/google-ads/api/fields/v9/ad_group_label) +- [campaigns](https://developers.google.com/google-ads/api/fields/v9/campaign) +- [campaign_labels](https://developers.google.com/google-ads/api/fields/v9/campaign_label) +- [click_view](https://developers.google.com/google-ads/api/reference/rpc/v9/ClickView) +- [keyword](https://developers.google.com/google-ads/api/fields/v9/keyword_view) +- [geographic](https://developers.google.com/google-ads/api/fields/v9/geographic_view) -1. Create an Google Ads Account. Here are [Google's instruction](https://support.google.com/google-ads/answer/6366720) on how to create one. -2. Create an Google Ads MANAGER Account. Here are [Google's instruction](https://ads.google.com/home/tools/manager-accounts/) on how to create one. -3. You should now have two Google Ads accounts: a normal account and a manager account. Link the Manager account to the normal account following [Google's documentation](https://support.google.com/google-ads/answer/7459601). -4. Apply for a developer token \(**make sure you follow our** [**instructions**](google-ads.md#how-to-apply-for-the-developer-token)\) on your Manager account. This token allows you to access your data from the Google Ads API. Here are [Google's instructions](https://developers.google.com/google-ads/api/docs/first-call/dev-token). The docs are a little unclear on this point, but you will _not_ be able to access your data via the Google Ads API until this token is approved. You cannot use a test developer token, it has to be at least a basic developer token. It usually takes Google 24 hours to respond to these applications. This developer token is the value you will use in the `developer_token` field. -5. Fetch your `client_id`, `client_secret`, and `refresh_token`. Google provides [instructions](https://developers.google.com/google-ads/api/docs/first-call/overview) on how to do this. -6. Select your `customer_id`. The `customer_id` refers to the id of each of your Google Ads accounts. This is the 10 digit number in the top corner of the page when you are in Google Ads UI. The source will only pull data from the accounts for which you provide an id. If you are having trouble finding it, check out [Google's instructions](https://support.google.com/google-ads/answer/1704344). +Note that `ad_groups`, `ad_group_ads`, and `campaigns` contain a `labels` field, which should be joined against their respective `*_labels` streams if you want to view the actual labels. For example, the `ad_groups` stream contains an `ad_group.labels` field, which you would join against the `ad_group_labels` stream's `label.resource_name` field. -Wow! That was a lot of steps. We are working on making the OAuth flow for all of our connectors simpler \(allowing you to skip needing to get a `developer_token` and a `refresh_token` which are the most painful / time-consuming steps in this walkthrough\). +### Report Tables -### How to apply for the developer token +- [account_performance_report](https://developers.google.com/google-ads/api/docs/migration/mapping#account_performance) +- [ad_group_ad_report](https://developers.google.com/google-ads/api/docs/migration/mapping#ad_performance) +- [display_keyword_report](https://developers.google.com/google-ads/api/docs/migration/mapping#display_keyword_performance) +- [display_topics_report](https://developers.google.com/google-ads/api/docs/migration/mapping#display_topics_performance) +- [shopping_performance_report](https://developers.google.com/google-ads/api/docs/migration/mapping#shopping_performance) +- [user_location_report](https://developers.google.com/google-ads/api/fields/v9/user_location_view) -Google is very picky about which software and which use case can get access to a developer token. The Airbyte team has worked with the Google Ads team to whitelist Airbyte and make sure you can get one \(see [issue 1981](https://github.com/airbytehq/airbyte/issues/1981) for more information\). +**Note**: Due to constraints from the Google Ads API, the `click_view` stream retrieves data one day at a time and can only retrieve data newer than 90 days ago -When you apply for a token, you need to mention: +**Note**: Due to constraints from the Google Ads API, [metrics](https://developers.google.com/google-ads/api/fields/v9/metrics) cannot be requested for a manager account. Therefore, report streams are only available when pulling data from a non-manager account. -- Why you need the token \(eg: want to run some internal analytics...\) -- That you will be using the Airbyte Open Source project -- That you have full access to the code base \(because we're open source\) -- That you have full access to the server running the code \(because you're self-hosting Airbyte\) +**Note**: For incremental streams data is synced up to the previous day using your Google Ads account time zone. The reason is that Google Ads can filter data only by [date](https://developers.google.com/google-ads/api/fields/v9/ad_group_ad#segments.date) without time. Also, some reports cannot load data in real time due to Google Ads [limitations](https://support.google.com/google-ads/answer/2544985?hl=en). -#### Understanding Google Ads Query Language +## Understanding Google Ads Query Language The Google Ads Query Language can query the Google Ads API. Check out [Google Ads Query Language](https://developers.google.com/google-ads/api/docs/query/overview) and the [query builder](https://developers.google.com/google-ads/api/docs/query/overview). You can add these as custom queries when configuring the Google Ads source. -## Rate Limiting & Performance Considerations \(Airbyte Open Source\) +## Performance considerations This source is constrained by whatever API limits are set for the Google Ads that is used. You can read more about those limits in the [Google Developer docs](https://developers.google.com/google-ads/api/docs/best-practices/quotas). -## CHANGELOG +## Changelog | Version | Date | Pull Request | Subject | -| :------- | :--------- |:---------------------------------------------------------|:---------------------------------------------------------------------------------------------| +|:---------|:-----------|:---------------------------------------------------------|:---------------------------------------------------------------------------------------------| +| `0.1.38` | 2022-05-12 | [12807](https://github.com/airbytehq/airbyte/pull/12807) | Documentation updates | | `0.1.37` | 2022-05-06 | [12651](https://github.com/airbytehq/airbyte/pull/12651) | Improve integration and unit tests | | `0.1.36` | 2022-04-19 | [12158](https://github.com/airbytehq/airbyte/pull/12158) | Fix `*_labels` streams data type | | `0.1.35` | 2022-04-18 | [9310](https://github.com/airbytehq/airbyte/pull/9310) | Add new fields to reports |