Модель доступа в 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.V25.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