Модель доступа в Google Рекламе

Существует два типа аккаунтов Google Рекламы: управляющие аккаунты и аккаунты рекламодателей. Подробное описание того, как эти и другие термины (например, "клиентский аккаунт" и "клиент") связаны между собой, вы найдете в статье Типы аккаунтов.

Управляющие аккаунты могут управлять другими управляющими аккаунтами Google Рекламы или аккаунтами рекламодателей Google Рекламы. Вы можете связать аккаунт рекламодателя с управляющим аккаунтом и управлять им через управляющий аккаунт. Общая структура связей представляет собой направленный ациклический граф, в котором аккаунты рекламодателей находятся на уровне конечных узлов.

Вы можете предоставить доступ к аккаунтам Google Рекламы отдельным пользователям или сервисным аккаунтам. Предоставить пользователям доступ к аккаунту рекламодателя можно двумя способами:

  • Предоставьте пользователю прямой доступ к аккаунту рекламодателя, пригласив его в этот аккаунт.
  • Предоставьте пользователю косвенный доступ к аккаунту рекламодателя, пригласив его в управляющий аккаунт, связанный с этим аккаунтом. Пользователь получает доступ к аккаунту рекламодателя, поскольку управляющий аккаунт имеет доступ ко всем связанным с ним аккаунтам.

Вы также можете назначать роли пользователей, когда приглашаете пользователя управлять аккаунтом.

Рассмотрим следующую иерархию аккаунтов. Предположим, что у всех пользователей стандартный доступ.

Диаграмма, на которой показаны управляющие аккаунты M1, M2 и M3, связанные с аккаунтами рекламодателей A1–A4.

В таблице ниже приведена сводная информация о структуре аккаунта.

Пользователь Имеет прямой доступ к Имеет косвенный доступ к
U1, SA1 M1 M2, A1, A2, A3
U2 M2, M3 A1, A2, A3, A4
U3 A4  

Идентификатор клиента для входа

У пользователя может быть доступ к нескольким иерархиям аккаунтов. При вызове API в таких случаях необходимо указать корневой аккаунт, чтобы правильно определить уровни авторизации и доступа к аккаунту. Для этого включите в запрос к API заголовок login-customer-id.

В таблице ниже на основе иерархии аккаунтов из предыдущего примера показано, какие идентификаторы клиентов можно использовать для входа и к каким аккаунтам можно выполнять вызовы.

Пользователь Идентификатор клиента, который нужно использовать для входа Аккаунты, к которым выполняются вызовы API
U1, SA1 M1 M1, M2, A1, A2, A3
U2 M2 M2, A1, A2, A3
U2 M3 M3, A1, A4
U3 A4 A4

Заголовок login-customer-id можно не указывать, если у пользователя есть прямой доступ к аккаунту Google Рекламы, к которому вы обращаетесь. Например, вам не нужно указывать заголовок login-customer-id, если вы используете учетные данные U3 для вызова A4, поскольку серверы Google Рекламы могут правильно определить уровень доступа по идентификатору клиента (A4).

Если вы используете клиентскую библиотеку Google Ads API, укажите заголовок login-customer-id с помощью следующих настроек.

Java

Добавьте в файл ads.properties следующий параметр:

api.googleads.loginCustomerId=INSERT_LOGIN_CUSTOMER_ID_HERE

.NET

Добавьте следующую настройку при инициализации объекта GoogleAdsConfig и используйте ее для создания объекта GoogleAdsClient.

GoogleAdsConfig config = new GoogleAdsConfig()
{
    // ...
    LoginCustomerId = "INSERT_LOGIN_CUSTOMER_ID_HERE"
};
GoogleAdsClient client = new GoogleAdsClient(config);

Python

Добавьте в файл google-ads.yaml следующий параметр:

login_customer_id: INSERT_LOGIN_CUSTOMER_ID_HERE

PHP

Добавьте в файл google_ads_php.ini следующий параметр:

[GOOGLE_ADS]
loginCustomerId = "INSERT_LOGIN_CUSTOMER_ID_HERE"

Ruby

Добавьте в файл google_ads_config.rb следующий параметр:

Google::Ads::GoogleAds::Config.new do |c|
  c.login_customer_id = 'INSERT_LOGIN_CUSTOMER_ID_HERE'
end

Создайте экземпляр GoogleAdsClient, указав путь к этому файлу.

client = Google::Ads::GoogleAds::GoogleAdsClient.new(
  'path/to/google_ads_config.rb'
)

Perl

Добавьте в файл googleads.properties следующий параметр:

loginCustomerId=INSERT_LOGIN_CUSTOMER_ID_HERE

curl

При запуске команды curl укажите следующий аргумент командной строки:

-H "login-customer-id: INSERT_LOGIN_CUSTOMER_ID_HERE"

Чтобы получить список аккаунтов, к которым у пользователя есть прямой доступ, используйте метод CustomerService.ListAccessibleCustomers. Эти аккаунты можно использовать в качестве допустимых значений для заголовка login-customer-id.

Java

private void runExample(GoogleAdsClient client) {
  // Optional: Change credentials to use a different refresh token, to retrieve customers
  //           available for a specific user.
  //
  // UserCredentials credentials =
  //     UserCredentials.newBuilder()
  //         .setClientId("INSERT_OAUTH_CLIENT_ID")
  //         .setClientSecret("INSERT_OAUTH_CLIENT_SECRET")
  //         .setRefreshToken("INSERT_REFRESH_TOKEN")
  //         .build();
  //
  // client = client.toBuilder().setCredentials(credentials).build();

  try (CustomerServiceClient customerService =
      client.getLatestVersion().createCustomerServiceClient()) {
    ListAccessibleCustomersResponse response =
        customerService.listAccessibleCustomers(
            ListAccessibleCustomersRequest.newBuilder().build());

    System.out.printf("Total results: %d%n", response.getResourceNamesCount());

    for (String customerResourceName : response.getResourceNamesList()) {
      System.out.printf("Customer resource name: %s%n", customerResourceName);
    }
  }
}
      

C#

public void Run(GoogleAdsClient client)
{
    // Get the CustomerService.
    CustomerServiceClient customerService = client.GetService(Services.V26.CustomerService);

    try
    {
        // Retrieve the list of customer resources.
        string[] customerResourceNames = customerService.ListAccessibleCustomers();

        // Display the result.
        foreach (string customerResourceName in customerResourceNames)
        {
            Console.WriteLine(
                $"Found customer with resource name = '{customerResourceName}'.");
        }
    }
    catch (GoogleAdsException e)
    {
        Console.WriteLine("Failure:");
        Console.WriteLine($"Message: {e.Message}");
        Console.WriteLine($"Failure: {e.Failure}");
        Console.WriteLine($"Request ID: {e.RequestId}");
        throw;
    }
}
      

PHP

public static function runExample(GoogleAdsClient $googleAdsClient)
{
    $customerServiceClient = $googleAdsClient->getCustomerServiceClient();

    // Issues a request for listing all accessible customers.
    $accessibleCustomers =
        $customerServiceClient->listAccessibleCustomers(new ListAccessibleCustomersRequest());
    print 'Total results: ' . count($accessibleCustomers->getResourceNames()) . PHP_EOL;

    // Iterates over all accessible customers' resource names and prints them.
    foreach ($accessibleCustomers->getResourceNames() as $resourceName) {
        /** @var string $resourceName */
        printf("Customer resource name: '%s'%s", $resourceName, PHP_EOL);
    }
}
      

Python

def main(client: GoogleAdsClient) -> None:
    customer_service: CustomerServiceClient = client.get_service(
        "CustomerService"
    )

    accessible_customers: ListAccessibleCustomersResponse = (
        customer_service.list_accessible_customers()
    )
    result_total: int = len(accessible_customers.resource_names)
    print(f"Total results: {result_total}")

    resource_names: List[str] = accessible_customers.resource_names
    for resource_name in resource_names:  # resource_name is implicitly str
        print(f'Customer resource name: "{resource_name}"')
      

Ruby

def list_accessible_customers()
  # GoogleAdsClient will read a config file from
  # ENV['HOME']/google_ads_config.rb when called without parameters
  client = Google::Ads::GoogleAds::GoogleAdsClient.new

  accessible_customers = client.service.customer.list_accessible_customers().resource_names

  accessible_customers.each do |resource_name|
    puts "Customer resource name: #{resource_name}"
  end
end
      

Perl

sub list_accessible_customers {
  my ($api_client) = @_;

  my $list_accessible_customers_response =
    $api_client->CustomerService()->list_accessible_customers();

  printf "Total results: %d.\n",
    scalar @{$list_accessible_customers_response->{resourceNames}};

  foreach
    my $resource_name (@{$list_accessible_customers_response->{resourceNames}})
  {
    printf "Customer resource name: '%s'.\n", $resource_name;
  }

  return 1;
}
      

curl

# Returns the resource names of customers directly accessible by the user
# authenticating the call.
#
# Variables:
#   API_VERSION,
#   OAUTH2_ACCESS_TOKEN:
#     See https://developers.google.com/google-ads/api/rest/auth#request_headers
#     for details.
#
curl -f --request GET \
"https://googleads.googleapis.com/v${API_VERSION}/customers:listAccessibleCustomers" \
--header "Content-Type: application/json" \
--header "Authorization: Bearer ${OAUTH2_ACCESS_TOKEN}" \
      

Что делать, если метод ListAccessibleCustomers не возвращает идентификатор клиента?

Если метод CustomerService.ListAccessibleCustomers не возвращает идентификатор клиента, который должен быть в результатах, этому может быть несколько объяснений.

  1. У вас есть доступ к идентификатору клиента, но он предоставлен через родительский управляющий аккаунт. Например, если вы вызовете метод ListAccessibleCustomers с учетными данными пользователя U1 из предыдущего примера, то в результатах будет возвращен только аккаунт M1, хотя у пользователя U1 есть доступ и к другим аккаунтам. Чтобы подтвердить эту возможность, получите иерархию аккаунтов, выполнив запросы search или searchStream к ресурсу customer_client для каждого из аккаунтов, возвращенных методом ListAccessibleCustomers. Для этого задайте каждый из этих аккаунтов в качестве login-customer-id, как описано в предыдущем разделе. Если у вас есть доступ к целевому аккаунту, вы можете получить его в рамках одной из иерархий аккаунтов.

  2. Вы используете неверные учетные данные OAuth. Чаще всего это происходит, если вы используете учетные данные другого пользователя. Например, это может произойти, если вы случайно перепутали учетные данные для песочницы или разработчика с учетными данными для рабочей среды или неправильно прочитали учетные данные другого пользователя из базы данных или локального кеша. Один из возможных способов устранения этой проблемы – использовать Google People API, чтобы получить имя и адрес электронной почты вошедшего в систему пользователя и проверить, совпадает ли он с ожидаемым адресом электронной почты.

  3. У вас нет доступа к аккаунту. Чтобы получить доступ к нужному аккаунту, следуйте инструкциям.

Роли пользователей

У Google Ads API нет собственной модели доступа, и он не использует отдельные области действия OAuth 2.0 для ограничения функциональности. Например, Google Ads API использует одни и те же области действия для операций чтения и записи. В Google Ads API используются те же роли пользователей, что и в Google Рекламе. Если роль пользователя назначена на уровне управляющего аккаунта, она наследуется всеми аккаунтами в иерархии. Если у пользователя есть конфликтующие роли в определенном аккаунте, правильный уровень определяется аккаунтом login-customer-id, указанным в запросе к API.

В таблице ниже используется иерархия аккаунтов из предыдущего примера и показано, как действуют различные роли пользователей.

Пользователь Роль пользователя предоставлена login-customer-id Действующий уровень доступа
SA1 Стандартный доступ к аккаунту M1 M1 Стандартный доступ на M1, M2, A1, A2, A3
U2 Стандартный доступ к M2
Доступ только для чтения к M3
M2 Стандартный доступ на M2, A1, A2, A3
U2 Стандартный доступ к M2
Доступ только для чтения к M3
M3 Доступ только для чтения на M3, A1, A4