Tìm hiểu về 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 tài khoản nhà quảng cáo Google Ads. Để biết giải thích chi tiết về mối quan 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 một tài khoản nhà quảng cáo với tài khoản người quản lý và 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 biểu đồ có hướng không chu kỳ với các tài khoản nhà quảng cáo ở cấp lá.

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

  • 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 trong đó.

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ý một tài khoản.

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

Sơ đồ hệ thống phân cấp tài khoản

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  

Đăng nhập mã khách hàng

Người dùng có thể có quyền truy cập vào nhiều hệ thống phân cấp tài khoản. Trong những trường hợp như vậy, khi thực hiện lệnh gọi API, bạn cần chỉ định tài khoản gốc để xác định chính xác quyền truy cập và cấp truy cập vào tài khoản. Bạn có thể thực hiện việc này bằng cách chỉ định tiêu đề login-customer-id trong yêu cầu API.

Bảng sau đây sử dụng hệ thống phân cấp tài khoản trong 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ể thực hiện lệnh gọi.

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 đang sử dụng một trong các thư viện ứng dụng, hãy sử 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

C#

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

GoogleAdsConfig config = new GoogleAdsConfig()
{
    ...
    LoginCustomerId = ******
};
GoogleAdsClient client = new GoogleAdsClient(config);

PHP

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

[GOOGLE_ADS]
loginCustomerId = "INSERT_LOGIN_CUSTOMER_ID_HERE"

Python

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

login_customer_id: 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 chuyển đường dẫn đến vị trí 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: LOGIN_CUSTOMER_ID"

Bạn có thể sử dụng phương thức CustomerService.ListAccessibleCustomers để truy xuất danh sách các 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.V24.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,
#   DEVELOPER_TOKEN,
#   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 "developer-token: ${DEVELOPER_TOKEN}" \
--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 CustomerService.ListAccessibleCustomers phương thức không truy xuất được mã khách hàng mà bạn dự kiến sẽ xuất hiện trong kết quả, thì có thể là do một số nguyên nhân sau.

  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 tài khoản người quản lý mẹ. 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, bạn sẽ chỉ nhận được 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ệ thống phân cấp tài khoản cho từng tài khoản mà phương thức ListAccessibleCustomers trả về. Để thực hiện việc này, hãy đặt từng tài khoản này làm mã khách hàng đăng nhập, 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 sẽ có thể tìm nạp tài khoản đó trong một trong các hệ thống 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 trộn lẫn thông tin đăng nhập của hộp cát hoặc nhà phát triển với thông tin đăng nhập của môi trường thực tế hoặc đọc nhầm thông tin đăng nhập của một 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 bạn khắc phục vấn đề 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 và xác minh xem tên và địa chỉ email đó 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. Hãy làm theo hướng dẫn để có quyền truy cập vào tài khoản khách hàng chính xác.

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 so với các thao tác đọc/ghi. Thay vào đó, Google Ads API tuân theo các vai trò của người dùng mà Google Ads hỗ trợ. Khi một vai trò của người dùng được cấp cho một tài khoản ở cấp người quản lý, vai trò đó sẽ được các tài khoản trong hệ thống phân cấp kế thừa. Nếu người dùng có các vai trò xung đột đối với một tài khoản nhất định, thì cấp chính xác sẽ được giải quyết bằng tài khoản login-customer-id được chỉ định trong yêu cầu API.

Bảng sau đây sử dụng hệ thống 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ò của người dùng cho người dùng.

Người dùng Vai trò của người dùng được cấp 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 vào M1, M2, A1, A2, A3
U2 Quyền truy cập tiêu chuẩn vào M2
Quyền truy cập chỉ đọc vào M3
M2 Quyền truy cập tiêu chuẩn vào M2, A1, A2, A3
U2 Quyền truy cập tiêu chuẩn vào M2
Quyền truy cập chỉ đọc vào M3
M3 Quyền truy cập chỉ đọc vào M3, A1, A4