Deploy to production

This guide helps you choose and configure the appropriate authentication approach for your Data Manager API production deployment.

Choose your deployment scenario

Select the authentication approach that matches your application architecture and deployment environment:

For general guidance on Google Cloud authentication, see the Google Cloud authentication decision tree.

Workloads in Google Cloud

When running on Google Cloud, attach a service account directly to your compute resource or configure Workload Identity Federation for GKE. Client libraries use ADC to retrieve short-lived credentials for the service account automatically without requiring credential files or environment variables.

Compute Engine

When creating a virtual machine instance, specify the service account and the Data Manager API scope so access tokens returned by the instance metadata server include the required authorization.

gcloud compute instances create INSTANCE_NAME \
  --service-account="SERVICE_ACCOUNT_EMAIL" \
  --scopes="https://www.googleapis.com/auth/datamanager,https://www.googleapis.com/auth/cloud-platform"

To update the scopes or service account on an existing instance, stop the instance, update the configuration with set-service-account, and restart the instance:

gcloud compute instances stop INSTANCE_NAME

gcloud compute instances set-service-account \
  INSTANCE_NAME \
  --service-account="SERVICE_ACCOUNT_EMAIL" \
  --scopes="https://www.googleapis.com/auth/datamanager,https://www.googleapis.com/auth/cloud-platform"

gcloud compute instances start INSTANCE_NAME

Cloud Run

Specify the service account when deploying the service:

gcloud run deploy SERVICE_NAME \
  --image="IMAGE_URL" \
  --service-account="SERVICE_ACCOUNT_EMAIL"

Cloud Functions

Specify the service account when deploying the function:

gcloud functions deploy FUNCTION_NAME \
  --service-account="SERVICE_ACCOUNT_EMAIL" \
  --runtime="RUNTIME" \
  --trigger-http

GKE

  1. Enable Workload Identity Federation for GKE on your cluster.
  2. Bind your Kubernetes Service Account (KSA) to the Google Service Account (GSA):

    # Define the Kubernetes service account member:
    KUBERNETES_MEMBER="serviceAccount:PROJECT_ID.svc.id.goog[KUBERNETES_NAMESPACE/KUBERNETES_SA_NAME]"
    
    # Grant the Workload Identity User role to the Kubernetes service account:
    gcloud iam service-accounts add-iam-policy-binding \
      SERVICE_ACCOUNT_EMAIL \
      --role="roles/iam.workloadIdentityUser" \
      --member="${KUBERNETES_MEMBER}"
    
  3. Annotate the Kubernetes Service Account with the Google Service Account email:

    kubectl annotate serviceaccount KUBERNETES_SA_NAME \
      --namespace="KUBERNETES_NAMESPACE" \
      iam.gke.io/gcp-service-account="SERVICE_ACCOUNT_EMAIL"
    
  4. Specify the Kubernetes Service Account in your pod specification:

    apiVersion: v1
    kind: Pod
    metadata:
      name: data-manager-worker
    spec:
      serviceAccountName: KUBERNETES_SA_NAME
      containers:
      - name: worker
        image: IMAGE_URL
    

Verify IAM and account access

Before deploying your production application, verify that your service account has the necessary permissions:

  1. Google Cloud IAM permissions: Grant the service account the Service Usage Consumer role (roles/serviceusage.serviceUsageConsumer) in the Google Cloud project where the Data Manager API is enabled.

    gcloud projects add-iam-policy-binding PROJECT_ID \
      --member="serviceAccount:SERVICE_ACCOUNT_EMAIL" \
      --role="roles/serviceusage.serviceUsageConsumer"
    
  2. Destination account access: Grant the service account the required access to your destination accounts. For step-by-step instructions, see Set up account access.

Workloads outside Google Cloud

When running code in on-premises data centers or on other cloud providers, choose one of the following authentication mechanisms:

  • Workload Identity Federation (Recommended): Configure Workload Identity Federation to let your application exchange credentials from your external identity provider for short-lived Google Cloud credentials without managing service account keys. Generate a credential configuration file and provide it to ADC using the GOOGLE_APPLICATION_CREDENTIALS environment variable.

  • Service account keys (Fallback): If Workload Identity Federation is not available, create a service account key and provide it to ADC using the GOOGLE_APPLICATION_CREDENTIALS environment variable.

Set GOOGLE_APPLICATION_CREDENTIALS

Set the GOOGLE_APPLICATION_CREDENTIALS environment variable to the absolute path of the Workload Identity Federation credential configuration file or service account key file so client libraries can locate your credentials automatically using ADC.

Linux / macOS

Set the environment variable in your shell profile or deployment script:

export GOOGLE_APPLICATION_CREDENTIALS=\
  "/path/to/credentials.json"

Windows (PowerShell)

Set the environment variable in PowerShell:

$env:GOOGLE_APPLICATION_CREDENTIALS = `
  "C:\path\to\credentials.json"

Docker / Containers

Mount the credentials file into the container and set the environment variable:

ENV GOOGLE_APPLICATION_CREDENTIALS="/secrets/credentials.json"

Or pass the environment variable at runtime:

HOST_CREDS="/host/path/credentials.json"
docker run -e GOOGLE_APPLICATION_CREDENTIALS="/secrets/credentials.json" \
  -v "${HOST_CREDS}:/secrets/credentials.json:ro" \
  IMAGE_NAME

Kubernetes

Mount the credentials as a Secret and reference it in the pod's environment:

apiVersion: v1
kind: Pod
metadata:
  name: data-manager-worker
spec:
  containers:
  - name: worker
    image: IMAGE_URL
    env:
    - name: GOOGLE_APPLICATION_CREDENTIALS
      value: "/etc/secrets/google/credentials.json"
    volumeMounts:
    - name: credentials-volume
      mountPath: "/etc/secrets/google"
      readOnly: true
  volumes:
  - name: credentials-volume
    secret:
      secretName: data-manager-credentials

Authenticate REST and curl requests

If your automated pipeline makes raw HTTP requests with curl rather than using a client library, use the Google Cloud CLI to non-interactively authenticate and manage access tokens without manually signing tokens:

  1. Authorize the Google Cloud CLI using the credential file configured in your environment:

    gcloud auth login --cred-file="${GOOGLE_APPLICATION_CREDENTIALS}"
    
  2. Pass the generated access token in the Authorization header of your API requests:

    curl -X POST "https://datamanager.googleapis.com/v1/..." \
      -H "Authorization: Bearer $(gcloud auth print-access-token)" \
      -H "Content-Type: application/json" \
      -d @request.json
    

    The Google Cloud CLI automatically caches the access token and refreshes it before expiration.

Verify IAM and account access

Before deploying your production application, verify that your service account has the necessary permissions:

  1. Google Cloud IAM permissions: Grant the service account the Service Usage Consumer role (roles/serviceusage.serviceUsageConsumer) in the Google Cloud project where the Data Manager API is enabled.

    gcloud projects add-iam-policy-binding PROJECT_ID \
      --member="serviceAccount:SERVICE_ACCOUNT_EMAIL" \
      --role="roles/serviceusage.serviceUsageConsumer"
    
  2. Destination account access: Grant the service account the required access to your destination accounts. For step-by-step instructions, see Set up account access.

Act on behalf of users

Third-party platforms such as marketing platforms and agencies often need to send API requests on behalf of multiple advertisers who sign up for their service.

In this architecture, instead of using Application Default Credentials, use the OAuth 2.0 Web Server flow to obtain user credentials with offline access from each advertiser, and then use those credentials to configure the client library at runtime based on which advertiser account the request is managing.

Implement the OAuth 2.0 web flow

Here is how to set up user delegation for multi-tenant applications:

  1. Request offline access: Direct users to Google's OAuth consent screen requesting the https://www.googleapis.com/auth/datamanager scope with access_type=offline and prompt=consent. Your server exchanges the authorization code for an access token and a refresh_token. For step-by-step instructions, see OAuth 2.0 for Web Server Applications.

  2. Store credentials securely: Store each user's refresh token securely in an encrypted credential store associated with their account on your platform.

  3. Initialize client libraries at runtime: When sending an API request on behalf of a specific user, construct user credentials from the refresh token you stored for the user and the client ID and client secret for your app, and pass them when initializing the client:

    .NET

    using Google.Ads.DataManager.V1;
    using Google.Apis.Auth.OAuth2;
    
    UserCredential credential = CredentialFactory.FromJsonParameters<UserCredential>(
        new JsonCredentialParameters
        {
            Type = JsonCredentialParameters.AuthorizedUserCredentialType,
            ClientId = clientId,
            ClientSecret = clientSecret,
            RefreshToken = refreshToken
        });
    
    IngestionServiceClient client = new IngestionServiceClientBuilder
    {
        Credential = credential
    }.Build();
    

    Go

    import (
        "context"
    
        datamanager "cloud.google.com/go/datamanager/apiv1"
        "golang.org/x/oauth2"
        "golang.org/x/oauth2/google"
        "google.golang.org/api/option"
    )
    
    cfg := &oauth2.Config{
        ClientID:     clientID,
        ClientSecret: clientSecret,
        Endpoint:     google.Endpoint,
    }
    ts := cfg.TokenSource(ctx, &oauth2.Token{RefreshToken: refreshToken})
    
    client, err := datamanager.NewIngestionClient(ctx, option.WithTokenSource(ts))
    

    Java

    import com.google.ads.datamanager.v1.IngestionServiceClient;
    import com.google.ads.datamanager.v1.IngestionServiceSettings;
    import com.google.api.gax.core.FixedCredentialsProvider;
    import com.google.auth.oauth2.UserCredentials;
    
    UserCredentials credentials =
        UserCredentials.newBuilder()
            .setClientId(clientId)
            .setClientSecret(clientSecret)
            .setRefreshToken(refreshToken)
            .build();
    
    IngestionServiceSettings settings =
        IngestionServiceSettings.newBuilder()
            .setCredentialsProvider(FixedCredentialsProvider.create(credentials))
            .build();
    
    try (IngestionServiceClient client = IngestionServiceClient.create(settings)) {
      // Send API requests using client...
    }
    

    Node.js

    const {IngestionServiceClient} = require('@google-ads/datamanager').v1;
    const {UserRefreshClient} = require('google-auth-library');
    
    const authClient = new UserRefreshClient({
      clientId,
      clientSecret,
      refreshToken,
    });
    
    const client = new IngestionServiceClient({authClient});
    

    PHP

    use Google\Ads\DataManager\V1\Client\IngestionServiceClient;
    use Google\Auth\Credentials\UserRefreshCredentials;
    
    $credentials = new UserRefreshCredentials(
        null,
        [
            'client_id' => $clientId,
            'client_secret' => $clientSecret,
            'refresh_token' => $refreshToken,
        ]
    );
    
    $client = new IngestionServiceClient(['credentials' => $credentials]);
    

    Python

    from google.ads.datamanager_v1 import IngestionServiceClient
    from google.oauth2.credentials import Credentials
    
    credentials = Credentials.from_authorized_user_info({
        "client_id": client_id,
        "client_secret": client_secret,
        "refresh_token": refresh_token,
    })
    
    client = IngestionServiceClient(credentials=credentials)
    

    Ruby

    require "google/ads/data_manager/v1"
    require "googleauth"
    
    credentials = Google::Auth::UserRefreshCredentials.new(
      client_id: client_id,
      client_secret: client_secret,
      refresh_token: refresh_token
    )
    
    client = Google::Ads::DataManager::V1::IngestionService::Client.new do |config|
      config.credentials = credentials
    end
    

Complete OAuth app verification

Because https://www.googleapis.com/auth/datamanager is a sensitive scope, any Google Cloud app used to obtain user credentials from external Google Accounts must undergo Google OAuth verification before going to production:

  • Development: While the app's publishing status is set to Testing on the Audience page in the Google Cloud Console, only designated test accounts can authorize your application.
  • Production: Before making your application available to external users, set the publishing status to In production and submit the app for verification.

App verification isn't required for workloads that run using service accounts. In addition, there are some exceptions for scenarios such as internal applications. Check out When is verification not needed for details.

If your organization is an approved data partner, you can use partner links instead of managing per-user OAuth tokens for ongoing data ingestion.

With partner links, advertisers connect their accounts to your data partner account in the Google Ads, Display & Video 360, or Google Ad Manager UI. After the link is established, your application sends ingestion requests using your own service account credentials through ADC, avoiding the need to store and maintain long-lived user refresh tokens.

Production best practices

Review these key operational considerations when moving to production: