diff --git a/providers/google/docs/connections/google_ads.rst b/providers/google/docs/connections/google_ads.rst new file mode 100644 index 0000000000000..652eb8b63b87b --- /dev/null +++ b/providers/google/docs/connections/google_ads.rst @@ -0,0 +1,64 @@ + .. Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + .. http://www.apache.org/licenses/LICENSE-2.0 + + .. Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. + +.. _howto/connection:google_ads: + +Google Ads Connection +===================== + +The **Google Ads** connection type enables integrations with the Google Ads API. + +Default Connection IDs +---------------------- + +Hooks related to Google Ads use ``google_ads_default`` by default. + +Configuring the Connection +-------------------------- + +Developer token + Your Google Ads *developer token*. + + See the official guide on how to obtain a developer token: + + https://developers.google.com/google-ads/api/docs/first-call/dev-token + +OAuth2 client ID + The *client ID* from your Google Cloud OAuth 2.0 credentials. + +OAuth2 client secret + The *client secret* paired with the client ID above. + +OAuth2 refresh token + The *refresh token* generated for the client ID / secret pair. + +Authentication method + Either ``service_account`` (default) or ``developer_token``. + + Use ``service_account`` when authenticating with a Google service‑account key file + + specified via ``GOOGLE_APPLICATION_CREDENTIALS`` or a GCP connection. + +Extra (optional, JSON) + Additional client configuration, provided as a JSON dictionary. + Common keys include: + + ``login_customer_id`` + Customer ID to impersonate when using a manager account. + + ``linked_customer_id`` + Linked customer ID for certain account‑specific requests. diff --git a/providers/google/provider.yaml b/providers/google/provider.yaml index aa209c6fd486c..d9c4403575c33 100644 --- a/providers/google/provider.yaml +++ b/providers/google/provider.yaml @@ -1105,6 +1105,8 @@ connection-types: connection-type: gcpssh - hook-class-name: airflow.providers.google.leveldb.hooks.leveldb.LevelDBHook connection-type: leveldb + - hook-class-name: airflow.providers.google.ads.hooks.ads.GoogleAdsHook + connection-type: google_ads extra-links: - airflow.providers.google.cloud.links.alloy_db.AlloyDBBackupsLink diff --git a/providers/google/src/airflow/providers/google/ads/hooks/ads.py b/providers/google/src/airflow/providers/google/ads/hooks/ads.py index 14c279132bdb9..2f734aa8a9c1d 100644 --- a/providers/google/src/airflow/providers/google/ads/hooks/ads.py +++ b/providers/google/src/airflow/providers/google/ads/hooks/ads.py @@ -101,6 +101,40 @@ class GoogleAdsHook(BaseHook): :param api_version: The Google Ads API version to use. """ + conn_name_attr = "google_ads_conn_id" + default_conn_name = "google_ads_default" + conn_type = "google_ads" + hook_name = "Google Ads" + + @classmethod + def get_connection_form_widgets(cls) -> dict[str, Any]: + """Return connection widgets to add to Google Ads connection form.""" + from flask_appbuilder.fieldwidgets import BS3PasswordFieldWidget, BS3TextFieldWidget + from flask_babel import lazy_gettext + from wtforms import PasswordField, StringField + + return { + "developer_token": StringField(lazy_gettext("Developer token"), widget=BS3TextFieldWidget()), + "client_id": StringField(lazy_gettext("OAuth2 Client ID"), widget=BS3TextFieldWidget()), + "client_secret": PasswordField( + lazy_gettext("OAuth2 Client Secret"), widget=BS3PasswordFieldWidget() + ), + "refresh_token": PasswordField( + lazy_gettext("OAuth2 Refresh Token"), widget=BS3PasswordFieldWidget() + ), + } + + @classmethod + def get_ui_field_behaviour(cls) -> dict[str, Any]: + """Return custom UI field behaviour for Google Ads connection.""" + return { + "hidden_fields": ["host", "login", "schema", "port"], + "relabeling": {}, + "placeholders": { + "password": "Leave blank (optional)", + }, + } + def __init__( self, api_version: str | None = None, diff --git a/providers/google/src/airflow/providers/google/get_provider_info.py b/providers/google/src/airflow/providers/google/get_provider_info.py index 0d20284c96267..f1ded82262442 100644 --- a/providers/google/src/airflow/providers/google/get_provider_info.py +++ b/providers/google/src/airflow/providers/google/get_provider_info.py @@ -1368,6 +1368,10 @@ def get_provider_info(): "hook-class-name": "airflow.providers.google.leveldb.hooks.leveldb.LevelDBHook", "connection-type": "leveldb", }, + { + "hook-class-name": "airflow.providers.google.ads.hooks.ads.GoogleAdsHook", + "connection-type": "google_ads", + }, ], "extra-links": [ "airflow.providers.google.cloud.links.alloy_db.AlloyDBBackupsLink",