Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
119 changes: 119 additions & 0 deletions providers/google/docs/operators/marketing_platform/bid_manager.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
.. 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.

Google Bid Manager API Operators
=======================================
`Google Bid Manager API <https://developers.google.com/bid-manager/>`__ is a programmatic interface for the Display & Video 360 reporting feature.
It lets users build and run report queries, and download the resulting report file.

Prerequisite Tasks
^^^^^^^^^^^^^^^^^^

.. include:: /operators/_partials/prerequisite_tasks.rst

.. _howto/operator:GoogleBidManagerCreateQueryOperator:

Creating a Query
^^^^^^^^^^^^^^^^

To create a query using Bid Manager, use
:class:`~airflow.providers.google.marketing_platform.operators.bid_manager.GoogleBidManagerCreateQueryOperator`.

.. exampleinclude:: /../../google/tests/system/google/marketing_platform/example_bid_manager.py
:language: python
:dedent: 4
:start-after: [START howto_google_bid_manager_create_query_operator]
:end-before: [END howto_google_bid_manager_create_query_operator]

Use :ref:`Jinja templating <concepts:jinja-templating>` with
:template-fields:`airflow.providers.google.marketing_platform.operators.bid_manager.GoogleBidManagerCreateQueryOperator`
parameters which allow you to dynamically determine values. You can provide body definition using ``.json`` file
as this operator supports this template extension.
The result is saved to :ref:`XCom <concepts:xcom>`, which allows the result to be used by other operators.

.. _howto/operator:GoogleBidManagerRunQueryOperator:

Run Query
^^^^^^^^^

To run a query using Bid Manager, use
:class:`~airflow.providers.google.marketing_platform.operators.bid_manager.GoogleBidManagerRunQueryOperator`.

.. exampleinclude:: /../../google/tests/system/google/marketing_platform/example_bid_manager.py
:language: python
:dedent: 4
:start-after: [START howto_google_bid_manager_run_query_report_operator]
:end-before: [END howto_google_bid_manager_run_query_report_operator]

You can use :ref:`Jinja templating <concepts:jinja-templating>` with
:template-fields:`airflow.providers.google.marketing_platform.operators.bid_manager.GoogleBidManagerRunQueryOperator`
parameters which allow you to dynamically determine values.
The result is saved to :ref:`XCom <concepts:xcom>`, which allows the result to be used by other operators.

.. _howto/operator:GoogleBidManagerDeleteQueryOperator:

Deleting a Query
^^^^^^^^^^^^^^^^

To delete a query using Bid Manager, use
:class:`~airflow.providers.google.marketing_platform.operators.bid_manager.GoogleBidManagerDeleteQueryOperator`.

.. exampleinclude:: /../../google/tests/system/google/marketing_platform/example_bid_manager.py
:language: python
:dedent: 4
:start-after: [START howto_google_bid_manager_delete_query_operator]
:end-before: [END howto_google_bid_manager_delete_query_operator]

You can use :ref:`Jinja templating <concepts:jinja-templating>` with
:template-fields:`airflow.providers.google.marketing_platform.operators.bid_manager.GoogleBidManagerDeleteQueryOperator`
parameters which allow you to dynamically determine values.

.. _howto/operator:GoogleBidManagerRunQuerySensor:

Waiting for query
^^^^^^^^^^^^^^^^^

To wait for the report use
:class:`~airflow.providers.google.marketing_platform.sensors.bid_manager.GoogleBidManagerRunQuerySensor`.

.. exampleinclude:: /../../google/tests/system/google/marketing_platform/example_bid_manager.py
:language: python
:dedent: 4
:start-after: [START howto_google_bid_manager_wait_run_query_sensor]
:end-before: [END howto_google_bid_manager_wait_run_query_sensor]

Use :ref:`Jinja templating <concepts:jinja-templating>` with
:template-fields:`airflow.providers.google.marketing_platform.sensors.bid_manager.GoogleBidManagerRunQuerySensor`
parameters which allow you to dynamically determine values.

.. _howto/operator:GoogleBidManagerDownloadReportOperator:

Downloading a report
^^^^^^^^^^^^^^^^^^^^

To download a report to GCS bucket use
:class:`~airflow.providers.google.marketing_platform.operators.bid_manager.GoogleBidManagerDownloadReportOperator`.

.. exampleinclude:: /../../google/tests/system/google/marketing_platform/example_bid_manager.py
:language: python
:dedent: 4
:start-after: [START howto_google_bid_manager_get_report_operator]
:end-before: [END howto_google_bid_manager_get_report_operator]

Use :ref:`Jinja templating <concepts:jinja-templating>` with
:template-fields:`airflow.providers.google.marketing_platform.operators.bid_manager.GoogleBidManagerDownloadReportOperator`
parameters which allow you to dynamically determine values.
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@ Use :ref:`Jinja templating <concepts:jinja-templating>` with
:template-fields:`airflow.providers.google.marketing_platform.operators.display_video.GoogleDisplayVideo360CreateSDFDownloadTaskOperator`
parameters which allow you to dynamically determine values.


.. _howto/operator:GoogleDisplayVideo360SDFtoGCSOperator:

Save SDF files in the Google Cloud Storage
Expand Down
15 changes: 15 additions & 0 deletions providers/google/provider.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -468,6 +468,12 @@ integrations:
how-to-guide:
- /docs/apache-airflow-providers-google/operators/cloud/ray.rst
tags: [gcp]
- integration-name: Google Bid Manager API
external-doc-url: https://developers.google.com/bid-manager
logo: /docs/integration-logos/Google-Search-Ads360.png
how-to-guide:
- /docs/apache-airflow-providers-google/operators/marketing_platform/bid_manager.rst
tags: [gmp]

operators:
- integration-name: Google Ads
Expand Down Expand Up @@ -633,6 +639,9 @@ operators:
- integration-name: Google Ray
python-modules:
- airflow.providers.google.cloud.operators.ray
- integration-name: Google Bid Manager API
python-modules:
- airflow.providers.google.marketing_platform.operators.bid_manager

sensors:
- integration-name: Google BigQuery
Expand Down Expand Up @@ -698,6 +707,9 @@ sensors:
- integration-name: Google Cloud Tasks
python-modules:
- airflow.providers.google.cloud.sensors.tasks
- integration-name: Google Bid Manager API
python-modules:
- airflow.providers.google.marketing_platform.sensors.bid_manager

filesystems:
- airflow.providers.google.cloud.fs.gcs
Expand Down Expand Up @@ -917,6 +929,9 @@ hooks:
- integration-name: Google Ray
python-modules:
- airflow.providers.google.cloud.hooks.ray
- integration-name: Google Bid Manager API
python-modules:
- airflow.providers.google.marketing_platform.hooks.bid_manager

bundles:
- integration-name: Google Cloud Storage (GCS)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -480,6 +480,15 @@ def get_provider_info():
"how-to-guide": ["/docs/apache-airflow-providers-google/operators/cloud/ray.rst"],
"tags": ["gcp"],
},
{
"integration-name": "Google Bid Manager API",
"external-doc-url": "https://developers.google.com/bid-manager",
"logo": "/docs/integration-logos/Google-Search-Ads360.png",
"how-to-guide": [
"/docs/apache-airflow-providers-google/operators/marketing_platform/bid_manager.rst"
],
"tags": ["gmp"],
},
],
"operators": [
{
Expand Down Expand Up @@ -701,6 +710,10 @@ def get_provider_info():
"integration-name": "Google Ray",
"python-modules": ["airflow.providers.google.cloud.operators.ray"],
},
{
"integration-name": "Google Bid Manager API",
"python-modules": ["airflow.providers.google.marketing_platform.operators.bid_manager"],
},
],
"sensors": [
{
Expand Down Expand Up @@ -787,6 +800,10 @@ def get_provider_info():
"integration-name": "Google Cloud Tasks",
"python-modules": ["airflow.providers.google.cloud.sensors.tasks"],
},
{
"integration-name": "Google Bid Manager API",
"python-modules": ["airflow.providers.google.marketing_platform.sensors.bid_manager"],
},
],
"filesystems": ["airflow.providers.google.cloud.fs.gcs"],
"asset-uris": [
Expand Down Expand Up @@ -1069,6 +1086,10 @@ def get_provider_info():
"integration-name": "Google Ray",
"python-modules": ["airflow.providers.google.cloud.hooks.ray"],
},
{
"integration-name": "Google Bid Manager API",
"python-modules": ["airflow.providers.google.marketing_platform.hooks.bid_manager"],
},
],
"bundles": [
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
#
# 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.
"""This module contains Google Bid Manager API hook."""

from __future__ import annotations

from collections.abc import Sequence
from typing import Any

from googleapiclient.discovery import Resource, build

from airflow.providers.google.common.hooks.base_google import GoogleBaseHook


class GoogleBidManagerHook(GoogleBaseHook):
"""Hook for Google Bid Manager API."""

_conn: Resource | None = None

def __init__(
self,
api_version: str = "v2",
gcp_conn_id: str = "google_cloud_default",
impersonation_chain: str | Sequence[str] | None = None,
**kwargs,
) -> None:
super().__init__(
gcp_conn_id=gcp_conn_id,
impersonation_chain=impersonation_chain,
**kwargs,
)
self.api_version = api_version

def get_conn(self) -> Resource:
"""Retrieve connection to Bid Manager API."""
if not self._conn:
http_authorized = self._authorize()
self._conn = build(
"doubleclickbidmanager",
self.api_version,
http=http_authorized,
cache_discovery=False,
)
return self._conn

def create_query(self, query: dict[str, Any]) -> dict:
"""
Create a query.

:param query: Query object to be passed to request body.
"""
response = self.get_conn().queries().create(body=query).execute(num_retries=self.num_retries)
return response

def delete_query(self, query_id: str) -> None:
"""
Delete a stored query as well as the associated stored reports.

:param query_id: Query ID to delete.
"""
self.get_conn().queries().delete(queryId=query_id).execute(num_retries=self.num_retries)

def get_query(self, query_id: str) -> dict:
"""
Retrieve a stored query.

:param query_id: Query ID to retrieve.
"""
response = self.get_conn().queries().get(queryId=query_id).execute(num_retries=self.num_retries)
return response

def list_queries(self) -> list[dict]:
"""Retrieve stored queries."""
response = self.get_conn().queries().list().execute(num_retries=self.num_retries)
return response.get("queries", [])

def run_query(self, query_id: str, params: dict[str, Any] | None) -> dict:
"""
Run a stored query to generate a report.

:param query_id: Query ID to run.
:param params: Parameters for the report.
"""
return (
self.get_conn().queries().run(queryId=query_id, body=params).execute(num_retries=self.num_retries)
)

def get_report(self, query_id: str, report_id: str) -> dict:
"""
Retrieve a report.

:param query_id: Query ID for which report was generated.
:param report_id: Report ID to retrieve.
"""
return (
self.get_conn()
.queries()
.reports()
.get(queryId=query_id, reportId=report_id)
.execute(num_retries=self.num_retries)
)

def list_reports(self, query_id: str) -> dict:
"""
Retrieve a list of reports.

:param query_id: Query ID for which report was generated.
"""
return (
self.get_conn().queries().reports().list(queryId=query_id).execute(num_retries=self.num_retries)
)
Loading
Loading