Tìm hiểu mô hình truy cập của Google Ads

Có hai loại tài khoản Google Ads: tài khoản người quản lý Google Ads và tài khoản nhà quảng cáo Google Ads. Để biết nội dung giải thích chi tiết về mối liên hệ giữa các thuật ngữ này và các thuật ngữ khác (như Tài khoản khách hàng và Khách hàng), hãy xem bài viết Các loại tài khoản.

Tài khoản người quản lý có thể quản lý các tài khoản người quản lý Google Ads khác hoặc tài khoản nhà quảng cáo Google Ads. Bạn có thể liên kết tài khoản nhà quảng cáo với tài khoản người quản lý, sau đó quản lý tài khoản nhà quảng cáo thông qua tài khoản người quản lý. Cấu trúc liên kết tổng thể là một đồ thị có hướng không tuần hoàn với các tài khoản nhà quảng cáo ở cấp lá.

Bạn có thể cấp cho người dùng cá nhân hoặc tài khoản dịch vụ quyền truy cập vào tài khoản Google Ads. Có hai cách để cấp cho người dùng quyền truy cập vào tài khoản nhà quảng cáo:

  • Cấp cho người dùng quyền truy cập trực tiếp vào tài khoản nhà quảng cáo bằng cách mời họ vào tài khoản đó.
  • Cấp cho người dùng quyền truy cập gián tiếp vào tài khoản nhà quảng cáo bằng cách mời họ vào một tài khoản người quản lý được liên kết với tài khoản đó. Người dùng có quyền truy cập vào tài khoản nhà quảng cáo vì tài khoản người quản lý có quyền truy cập vào tất cả các tài khoản được liên kết với tài khoản đó.

Bạn cũng có thể chỉ định vai trò của người dùng khi mời người dùng quản lý tài khoản.

Hãy xem xét hệ thống phân cấp tài khoản sau đây. Giả sử tất cả người dùng đều có quyền truy cập Tiêu chuẩn.

Sơ đồ cho thấy các tài khoản người quản lý M1, M2 và M3 được liên kết với các tài khoản nhà quảng cáo từ A1 đến A4.

Bảng sau đây tóm tắt cấu trúc tài khoản này.

Người dùng Có quyền truy cập trực tiếp vào Có quyền truy cập gián tiếp vào
U1, SA1 M1 M2, A1, A2, A3
U2 M2, M3 A1, A2, A3, A4
U3 A4  

Mã khách hàng đăng nhập

Một người dùng có thể có quyền truy cập vào nhiều hệ phân cấp tài khoản. Khi thực hiện lệnh gọi API trong những trường hợp như vậy, bạn cần chỉ định tài khoản gốc sẽ được dùng để xác định chính xác cấp truy cập và uỷ quyền của tài khoản. Để làm việc này, hãy thêm tiêu đề login-customer-id vào yêu cầu API của bạn.

Bảng sau đây sử dụng hệ thống phân cấp tài khoản từ ví dụ trước để cho biết mã khách hàng đăng nhập mà bạn có thể sử dụng và danh sách tài khoản tương ứng mà bạn có thể gọi đến.

Người dùng Mã khách hàng đăng nhập cần sử dụng Tài khoản để thực hiện lệnh gọi API
U1, SA1 M1 M1, M2, A1, A2, A3
U2 M2 M2, A1, A2, A3
U2 M3 M3, A1, A4
U3 A4 A4

Bạn có thể bỏ qua việc cung cấp tiêu đề login-customer-id nếu người dùng có quyền truy cập trực tiếp vào tài khoản Google Ads mà bạn đang thực hiện lệnh gọi. Ví dụ: bạn không cần chỉ định tiêu đề login-customer-id khi sử dụng thông tin đăng nhập U3 để thực hiện lệnh gọi đến A4, vì máy chủ Google Ads có thể xác định chính xác cấp truy cập từ mã khách hàng (A4).

Nếu bạn sử dụng thư viện ứng dụng Google Ads API, hãy dùng các chế độ cài đặt sau để chỉ định tiêu đề login-customer-id.

Java

Thêm chế độ cài đặt sau vào tệp ads.properties.

api.googleads.loginCustomerId=INSERT_LOGIN_CUSTOMER_ID_HERE

.NET

Thêm chế độ cài đặt sau khi bạn khởi động đối tượng GoogleAdsConfig và sử dụng đối tượng đó để tạo đối tượng GoogleAdsClient.

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

Python

Thêm chế độ cài đặt sau vào tệp google-ads.yaml.

login_customer_id: INSERT_LOGIN_CUSTOMER_ID_HERE

PHP

Thêm chế độ cài đặt sau vào tệp google_ads_php.ini.

[GOOGLE_ADS]
loginCustomerId = "INSERT_LOGIN_CUSTOMER_ID_HERE"

Ruby

Thêm chế độ cài đặt sau vào tệp google_ads_config.rb.

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

Tạo một thực thể GoogleAdsClient bằng cách truyền đường dẫn đến nơi bạn lưu giữ tệp này.

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

Perl

Thêm chế độ cài đặt sau vào tệp googleads.properties.

loginCustomerId=INSERT_LOGIN_CUSTOMER_ID_HERE

curl

Chỉ định đối số dòng lệnh sau khi chạy lệnh curl.

-H "login-customer-id: INSERT_LOGIN_CUSTOMER_ID_HERE"

Bạn có thể sử dụng phương thức CustomerService.ListAccessibleCustomers để truy xuất danh sách tài khoản mà người dùng có quyền truy cập trực tiếp. Bạn có thể sử dụng các tài khoản này làm giá trị hợp lệ cho tiêu đề 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}" \
      

Nếu phương thức ListAccessibleCustomers không truy xuất được mã khách hàng của tôi thì sao?

Nếu phương thức CustomerService.ListAccessibleCustomers không truy xuất được mã khách hàng mà bạn muốn xuất hiện trong kết quả, thì có thể là do một số nguyên nhân.

  1. Bạn có quyền truy cập vào mã khách hàng, nhưng quyền truy cập này được cấp thông qua một tài khoản người quản lý cấp cao. Ví dụ: nếu bạn gọi phương thức ListAccessibleCustomers bằng thông tin đăng nhập của người dùng U1 trong ví dụ trước, thì phương thức này chỉ trả về M1 trong kết quả, mặc dù U1 có quyền truy cập vào nhiều tài khoản hơn. Để xác nhận khả năng này, hãy truy xuất hệ phân cấp tài khoản bằng cách thực thi truy vấn search hoặc searchStream đối với tài nguyên customer_client cho từng tài khoản được phương thức ListAccessibleCustomers trả về. Để làm việc này, hãy đặt từng tài khoản này làm login-customer-id, như mô tả trong phần trước. Nếu có quyền truy cập vào tài khoản mục tiêu, bạn có thể tìm nạp tài khoản đó trong một trong các hệ phân cấp tài khoản.

  2. Bạn đang sử dụng thông tin đăng nhập OAuth không chính xác. Trường hợp phổ biến nhất là bạn đang sử dụng thông tin đăng nhập của một người dùng khác. Ví dụ: có thể là do vô tình nhầm lẫn thông tin xác thực hộp cát hoặc thông tin xác thực của nhà phát triển với thông tin xác thực chính thức, hoặc đọc nhầm thông tin xác thực của người dùng khác từ cơ sở dữ liệu hoặc bộ nhớ đệm cục bộ. Một cách có thể giúp khắc phục sự cố này là sử dụng Google People API để truy xuất tên và địa chỉ email của người dùng đã đăng nhập, sau đó xác minh xem thông tin đó có khớp với địa chỉ email mà bạn mong đợi hay không.

  3. Bạn không có quyền truy cập vào tài khoản này. Làm theo hướng dẫn về quyền truy cập vào tài khoản để có quyền truy cập vào đúng tài khoản khách hàng.

Vai trò của người dùng

Google Ads API không có mô hình truy cập riêng hoặc sử dụng các phạm vi OAuth 2.0 riêng để giới hạn chức năng. Ví dụ: Google Ads API sử dụng cùng một phạm vi cho các thao tác chỉ đọc và thao tác đọc-ghi. Thay vào đó, API Google Ads tuân theo cùng vai trò người dùng mà Google Ads hỗ trợ. Khi một vai trò người dùng được cấp cho một tài khoản ở cấp người quản lý, thì các tài khoản trong hệ phân cấp sẽ kế thừa vai trò đó. Nếu một người dùng có các vai trò xung đột với một tài khoản nhất định, thì cấp truy cập chính xác sẽ được xác định theo tài khoản login-customer-id được chỉ định trong yêu cầu API.

Bảng sau đây sử dụng hệ phân cấp tài khoản trong ví dụ trước và cho thấy hiệu quả của việc cấp nhiều vai trò người dùng cho người dùng.

Người dùng Đã cấp vai trò người dùng login-customer-id Cấp truy cập thực tế
SA1 Quyền truy cập tiêu chuẩn vào tài khoản M1 M1 Quyền truy cập tiêu chuẩn trên M1, M2, A1, A2, A3
U2 Quyền truy cập tiêu chuẩn trên M2
Quyền chỉ có thể đọc trên M3
M2 Quyền truy cập tiêu chuẩn trên M2, A1, A2, A3
U2 Quyền truy cập tiêu chuẩn trên M2
Quyền chỉ có thể đọc trên M3
M3 Quyền chỉ có thể đọc trên M3, A1, A4