Get Account Hierarchy

Each top-level manager account can branch out to manage client accounts or other manager accounts. Those manager accounts can then branch out to manage more client accounts or other manager accounts, and so on.

You can get the account hierarchy of your manager account, by building a Google Ads Query Language statement to query all the child accounts specified by the client_customer field from CustomerClient , and executing it recursively on the sub-manager accounts. You'll be able to check which accounts are directly linked to your manager account and which are indirectly linked through sub-managers.

Here is a code example demonstrating how to get the account hierarchy, along with individual customer details for each account.

Java

 // Copyright 2020 Google LLC 
 // 
 // Licensed under the Apache License, Version 2.0 (the "License"); 
 // you may not use this file except in compliance with the License. 
 // You may obtain a copy of the License at 
 // 
 //     https://www.apache.org/licenses/LICENSE-2.0 
 // 
 // Unless required by applicable law or agreed to in writing, software 
 // distributed under the License is distributed on an "AS IS" BASIS, 
 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
 // See the License for the specific language governing permissions and 
 // limitations under the License. 
 package 
  
 com.google.ads.googleads.examples.accountmanagement 
 ; 
 import 
  
 com.beust.jcommander.Parameter 
 ; 
 import 
  
 com.google.ads.googleads.examples.utils.ArgumentNames 
 ; 
 import 
  
 com.google.ads.googleads.examples.utils.CodeSampleParams 
 ; 
 import 
  
 com.google.ads.googleads.lib.GoogleAdsClient 
 ; 
 import 
  
 com.google.ads.googleads.v21.errors.GoogleAdsError 
 ; 
 import 
  
 com.google.ads.googleads.v21.errors.GoogleAdsException 
 ; 
 import 
  
 com.google.ads.googleads.v21.resources.CustomerClient 
 ; 
 import 
  
 com.google.ads.googleads.v21.resources.CustomerName 
 ; 
 import 
  
 com.google.ads.googleads.v21.services.CustomerServiceClient 
 ; 
 import 
  
 com.google.ads.googleads.v21.services.GoogleAdsRow 
 ; 
 import 
  
 com.google.ads.googleads.v21.services.GoogleAdsServiceClient 
 ; 
 import 
  
 com.google.ads.googleads.v21.services.GoogleAdsServiceClient.SearchPagedResponse 
 ; 
 import 
  
 com.google.ads.googleads.v21.services.ListAccessibleCustomersRequest 
 ; 
 import 
  
 com.google.ads.googleads.v21.services.ListAccessibleCustomersResponse 
 ; 
 import 
  
 com.google.ads.googleads.v21.services.SearchGoogleAdsRequest 
 ; 
 import 
  
 com.google.common.base.Strings 
 ; 
 import 
  
 com.google.common.collect.ArrayListMultimap 
 ; 
 import 
  
 com.google.common.collect.Multimap 
 ; 
 import 
  
 java.io.FileNotFoundException 
 ; 
 import 
  
 java.io.IOException 
 ; 
 import 
  
 java.util.ArrayList 
 ; 
 import 
  
 java.util.HashMap 
 ; 
 import 
  
 java.util.LinkedList 
 ; 
 import 
  
 java.util.List 
 ; 
 import 
  
 java.util.Map 
 ; 
 import 
  
 java.util.Queue 
 ; 
 /** 
 * Gets the account hierarchy of the specified manager account and login customer ID. If you don't 
 * specify manager ID and login customer ID, the example will instead print the hierarchies of all 
 * accessible customer accounts for your authenticated Google account. Note that if the list of 
 * accessible customers for your authenticated Google account includes accounts within the same 
 * hierarchy, this example will retrieve and print the overlapping portions of the hierarchy for 
 * each accessible customer. 
 */ 
 public 
  
 class 
 GetAccountHierarchy 
  
 { 
  
 private 
  
 static 
  
 class 
 GetAccountHierarchyParams 
  
 extends 
  
 CodeSampleParams 
  
 { 
  
 @Parameter 
 ( 
 names 
  
 = 
  
 ArgumentNames 
 . 
 MANAGER_CUSTOMER_ID 
 ) 
  
 private 
  
 Long 
  
 managerId 
 ; 
  
 @Parameter 
 ( 
 names 
  
 = 
  
 ArgumentNames 
 . 
 LOGIN_CUSTOMER_ID 
 ) 
  
 private 
  
 Long 
  
 loginCustomerId 
 ; 
  
 } 
  
 public 
  
 static 
  
 void 
  
 main 
 ( 
 String 
 [] 
  
 args 
 ) 
  
 { 
  
 GetAccountHierarchyParams 
  
 params 
  
 = 
  
 new 
  
 GetAccountHierarchyParams 
 (); 
  
 if 
  
 ( 
 ! 
 params 
 . 
 parseArguments 
 ( 
 args 
 )) 
  
 { 
  
 // Optional: You may pass the managerId on the command line or specify a managerId here. If 
  
 // neither are set, a null value will be passed to the run example method, and the example 
  
 // will print the hierarchies of all accessible customer IDs. 
  
 // params.managerId = Long.parseLong("INSERT_MANAGER_ID_HERE"); 
  
 // Optional: You may pass the loginCustomerId on the command line or specify a loginCustomerId 
  
 // here if and only if the managerId is set. If the loginCustomerId is set neither on the 
  
 // command line nor below, a null value will be passed to the run example method, and the 
  
 // example will use each respective accessible customer ID as the loginCustomerId. 
  
 // params.loginCustomerId = Long.parseLong("INSERT_LOGIN_CUSTOMER_ID_HERE"); 
  
 } 
  
 if 
  
 ( 
 params 
 . 
 managerId 
  
 != 
  
 null 
 && 
 params 
 . 
 loginCustomerId 
  
 == 
  
 null 
 ) 
  
 { 
  
 System 
 . 
 err 
 . 
 println 
 ( 
 "loginCustomerId must be provided if managerId is provided." 
 ); 
  
 return 
 ; 
  
 } 
  
 else 
  
 if 
  
 ( 
 params 
 . 
 managerId 
  
 == 
  
 null 
 && 
 params 
 . 
 loginCustomerId 
  
 != 
  
 null 
 ) 
  
 { 
  
 System 
 . 
 err 
 . 
 println 
 ( 
 "loginCustomerId may not be provided if managerId is not provided." 
 ); 
  
 return 
 ; 
  
 } 
  
 GoogleAdsClient 
  
 googleAdsClient 
  
 = 
  
 null 
 ; 
  
 try 
  
 { 
  
 googleAdsClient 
  
 = 
  
 GoogleAdsClient 
 . 
 newBuilder 
 (). 
 fromPropertiesFile 
 (). 
 build 
 (); 
  
 } 
  
 catch 
  
 ( 
 FileNotFoundException 
  
 fnfe 
 ) 
  
 { 
  
 System 
 . 
 err 
 . 
 printf 
 ( 
  
 "Failed to load GoogleAdsClient configuration from file. Exception: %s%n" 
 , 
  
 fnfe 
 ); 
  
 System 
 . 
 exit 
 ( 
 1 
 ); 
  
 } 
  
 catch 
  
 ( 
 IOException 
  
 ioe 
 ) 
  
 { 
  
 System 
 . 
 err 
 . 
 printf 
 ( 
 "Failed to create GoogleAdsClient. Exception: %s%n" 
 , 
  
 ioe 
 ); 
  
 System 
 . 
 exit 
 ( 
 1 
 ); 
  
 } 
  
 try 
  
 { 
  
 new 
  
 GetAccountHierarchy 
 () 
  
 . 
 runExample 
 ( 
 googleAdsClient 
 , 
  
 params 
 . 
 managerId 
 , 
  
 params 
 . 
 loginCustomerId 
 ); 
  
 } 
  
 catch 
  
 ( 
 GoogleAdsException 
  
 gae 
 ) 
  
 { 
  
 // GoogleAdsException is the base class for most exceptions thrown by an API request. 
  
 // Instances of this exception have a message and a GoogleAdsFailure that contains a 
  
 // collection of GoogleAdsErrors that indicate the underlying causes of the 
  
 // GoogleAdsException. 
  
 System 
 . 
 err 
 . 
 printf 
 ( 
  
 "Request ID %s failed due to GoogleAdsException. Underlying errors:%n" 
 , 
  
 gae 
 . 
 getRequestId 
 ()); 
  
 int 
  
 i 
  
 = 
  
 0 
 ; 
  
 for 
  
 ( 
 GoogleAdsError 
  
 googleAdsError 
  
 : 
  
 gae 
 . 
 getGoogleAdsFailure 
 (). 
 getErrorsList 
 ()) 
  
 { 
  
 System 
 . 
 err 
 . 
 printf 
 ( 
 "  Error %d: %s%n" 
 , 
  
 i 
 ++ 
 , 
  
 googleAdsError 
 ); 
  
 } 
  
 System 
 . 
 exit 
 ( 
 1 
 ); 
  
 } 
  
 catch 
  
 ( 
 IOException 
  
 ioe 
 ) 
  
 { 
  
 System 
 . 
 err 
 . 
 printf 
 ( 
 "Request failed. Exception: %s%n" 
 , 
  
 ioe 
 ); 
  
 System 
 . 
 exit 
 ( 
 1 
 ); 
  
 } 
  
 } 
  
 /** 
 * Runs the example. 
 * 
 * @param googleAdsClient the Google Ads API client. 
 * @param managerId the root customer ID from which to begin the search. 
 * @param loginCustomerId the loginCustomerId used to create the GoogleAdsClient. 
 * @throws IOException if a Google Ads Client is not successfully created. 
 */ 
  
 private 
  
 void 
  
 runExample 
 ( 
 GoogleAdsClient 
  
 googleAdsClient 
 , 
  
 Long 
  
 managerId 
 , 
  
 Long 
  
 loginCustomerId 
 ) 
  
 throws 
  
 IOException 
  
 { 
  
 List<Long> 
  
 seedCustomerIds 
  
 = 
  
 new 
  
 ArrayList 
<> (); 
  
 if 
  
 ( 
 managerId 
  
 == 
  
 null 
 ) 
  
 { 
  
 // Gets the account hierarchies for all accessible customers. 
  
 seedCustomerIds 
  
 = 
  
 getAccessibleCustomers 
 ( 
 googleAdsClient 
 ); 
  
 } 
  
 else 
  
 { 
  
 // Only gets the hierarchy for the provided manager ID if provided. 
  
 seedCustomerIds 
 . 
 add 
 ( 
 managerId 
 ); 
  
 } 
  
 Map<CustomerClient 
 , 
  
 Multimap<Long 
 , 
  
 CustomerClient 
>>  
 allHierarchies 
  
 = 
  
 new 
  
 HashMap 
<> (); 
  
 List<Long> 
  
 accountsWithNoInfo 
  
 = 
  
 new 
  
 ArrayList 
<> (); 
  
 // Constructs a map of account hierarchies. 
  
 for 
  
 ( 
 Long 
  
 seedCustomerId 
  
 : 
  
 seedCustomerIds 
 ) 
  
 { 
  
 Map<CustomerClient 
 , 
  
 Multimap<Long 
 , 
  
 CustomerClient 
>>  
 customerClientToHierarchy 
  
 = 
  
 createCustomerClientToHierarchy 
 ( 
 loginCustomerId 
 , 
  
 seedCustomerId 
 ); 
  
 if 
  
 ( 
 customerClientToHierarchy 
  
 == 
  
 null 
 ) 
  
 { 
  
 accountsWithNoInfo 
 . 
 add 
 ( 
 seedCustomerId 
 ); 
  
 } 
  
 else 
  
 { 
  
 allHierarchies 
 . 
 putAll 
 ( 
 customerClientToHierarchy 
 ); 
  
 } 
  
 } 
  
 // Prints the IDs of any accounts that did not produce hierarchy information. 
  
 if 
  
 ( 
 ! 
 accountsWithNoInfo 
 . 
 isEmpty 
 ()) 
  
 { 
  
 System 
 . 
 out 
 . 
 println 
 ( 
  
 "Unable to retrieve information for the following accounts which are likely either test " 
  
 + 
  
 "accounts or accounts with setup issues. Please check the logs for details." 
 ); 
  
 for 
  
 ( 
 long 
  
 accountId 
  
 : 
  
 accountsWithNoInfo 
 ) 
  
 { 
  
 System 
 . 
 out 
 . 
 println 
 ( 
 accountId 
 ); 
  
 } 
  
 System 
 . 
 out 
 . 
 println 
 (); 
  
 } 
  
 int 
  
 depth 
  
 = 
  
 0 
 ; 
  
 // Prints the hierarchy information for all accounts for which there is hierarchy information 
  
 // available. 
  
 for 
  
 ( 
 CustomerClient 
  
 rootCustomerClient 
  
 : 
  
 allHierarchies 
 . 
 keySet 
 ()) 
  
 { 
  
 System 
 . 
 out 
 . 
 printf 
 ( 
 "Hierarchy of customer ID %d:%n" 
 , 
  
 rootCustomerClient 
 . 
 getId 
 ()); 
  
 printAccountHierarchy 
 ( 
 rootCustomerClient 
 , 
  
 allHierarchies 
 . 
 get 
 ( 
 rootCustomerClient 
 ), 
  
 depth 
 ); 
  
 System 
 . 
 out 
 . 
 println 
 (); 
  
 } 
  
 } 
  
 /** 
 * Creates a map between a CustomerClient and each of its managers' mappings. 
 * 
 * @param loginCustomerId the loginCustomerId used to create the GoogleAdsClient. 
 * @param seedCustomerId the ID of the customer at the root of the tree. 
 * @return a map between a CustomerClient and each of its managers' mappings if the account 
 *     hierarchy can be retrieved. If the account hierarchy cannot be retrieved, returns null. 
 * @throws IOException if a Google Ads Client is not successfully created. 
 */ 
  
 private 
  
 Map<CustomerClient 
 , 
  
 Multimap<Long 
 , 
  
 CustomerClient 
>>  
 createCustomerClientToHierarchy 
 ( 
  
 Long 
  
 loginCustomerId 
 , 
  
 long 
  
 seedCustomerId 
 ) 
  
 throws 
  
 IOException 
  
 { 
  
 Queue<Long> 
  
 managerAccountsToSearch 
  
 = 
  
 new 
  
 LinkedList 
<> (); 
  
 CustomerClient 
  
 rootCustomerClient 
  
 = 
  
 null 
 ; 
  
 // Creates a GoogleAdsClient with the specified loginCustomerId. See 
  
 // https://developers.google.com/google-ads/api/docs/concepts/call-structure#cid for more 
  
 // information. 
  
 GoogleAdsClient 
  
 googleAdsClient 
  
 = 
  
 GoogleAdsClient 
 . 
 newBuilder 
 () 
  
 . 
 fromPropertiesFile 
 () 
  
 . 
 setLoginCustomerId 
 ( 
 loginCustomerId 
  
 == 
  
 null 
  
 ? 
  
 seedCustomerId 
  
 : 
  
 loginCustomerId 
 ) 
  
 . 
 build 
 (); 
  
 // Creates the Google Ads Service client. 
  
 try 
  
 ( 
 GoogleAdsServiceClient 
  
 googleAdsServiceClient 
  
 = 
  
 googleAdsClient 
 . 
 getLatestVersion 
 (). 
 createGoogleAdsServiceClient 
 ()) 
  
 { 
  
 // Creates a query that retrieves all child accounts of the manager specified in search 
  
 // calls below. 
  
 String 
  
 query 
  
 = 
  
 "SELECT customer_client.client_customer, customer_client.level, " 
  
 + 
  
 "customer_client.manager, customer_client.descriptive_name, " 
  
 + 
  
 "customer_client.currency_code, customer_client.time_zone, " 
  
 + 
  
 "customer_client.id " 
  
 + 
  
 "FROM customer_client " 
  
 + 
  
 "WHERE customer_client.level <= 1" 
 ; 
  
 // Adds the seed customer ID to the list of IDs to be processed. 
  
 managerAccountsToSearch 
 . 
 add 
 ( 
 seedCustomerId 
 ); 
  
 // Performs a breadth-first search algorithm to build a mapping of managers to their 
  
 // child accounts. 
  
 Multimap<Long 
 , 
  
 CustomerClient 
>  
 customerIdsToChildAccounts 
  
 = 
  
 ArrayListMultimap 
 . 
 create 
 (); 
  
 while 
  
 ( 
 ! 
 managerAccountsToSearch 
 . 
 isEmpty 
 ()) 
  
 { 
  
 long 
  
 customerIdToSearchFrom 
  
 = 
  
 managerAccountsToSearch 
 . 
 poll 
 (); 
  
 SearchPagedResponse 
  
 response 
 ; 
  
 try 
  
 { 
  
 // Issues a search request. 
  
 response 
  
 = 
  
 googleAdsServiceClient 
 . 
 search 
 ( 
  
 SearchGoogleAdsRequest 
 . 
 newBuilder 
 () 
  
 . 
 setQuery 
 ( 
 query 
 ) 
  
 . 
 setCustomerId 
 ( 
 Long 
 . 
 toString 
 ( 
 customerIdToSearchFrom 
 )) 
  
 . 
 build 
 ()); 
  
 // Iterates over all rows in all pages to get all customer clients under the specified 
  
 // customer's hierarchy. 
  
 for 
  
 ( 
 GoogleAdsRow 
  
 googleAdsRow 
  
 : 
  
 response 
 . 
 iterateAll 
 ()) 
  
 { 
  
 CustomerClient 
  
 customerClient 
  
 = 
  
 googleAdsRow 
 . 
 getCustomerClient 
 (); 
  
 // Gets the CustomerClient object for the root customer in the tree. 
  
 if 
  
 ( 
 customerClient 
 . 
 getId 
 () 
  
 == 
  
 seedCustomerId 
 ) 
  
 { 
  
 rootCustomerClient 
  
 = 
  
 customerClient 
 ; 
  
 } 
  
 // The steps below map parent and children accounts. Continue here so that manager 
  
 // accounts exclude themselves from the list of their children accounts. 
  
 if 
  
 ( 
 customerClient 
 . 
 getId 
 () 
  
 == 
  
 customerIdToSearchFrom 
 ) 
  
 { 
  
 continue 
 ; 
  
 } 
  
 // For all level-1 (direct child) accounts that are manager accounts, the above 
  
 // query will be run against them to create a map of managers to their 
  
 // child accounts for printing the hierarchy afterwards. 
  
 customerIdsToChildAccounts 
 . 
 put 
 ( 
 customerIdToSearchFrom 
 , 
  
 customerClient 
 ); 
  
 // Checks if the child account is a manager itself so that it can later be processed 
  
 // and added to the map if it hasn't been already. 
  
 if 
  
 ( 
 customerClient 
 . 
 getManager 
 ()) 
  
 { 
  
 // A customer can be managed by multiple managers, so to prevent visiting the same 
  
 // customer multiple times, we need to check if it's already in the map. 
  
 boolean 
  
 alreadyVisited 
  
 = 
  
 customerIdsToChildAccounts 
 . 
 containsKey 
 ( 
 customerClient 
 . 
 getId 
 ()); 
  
 if 
  
 ( 
 ! 
 alreadyVisited 
 && 
 customerClient 
 . 
 getLevel 
 () 
  
 == 
  
 1 
 ) 
  
 { 
  
 managerAccountsToSearch 
 . 
 add 
 ( 
 customerClient 
 . 
 getId 
 ()); 
  
 } 
  
 } 
  
 } 
  
 } 
  
 catch 
  
 ( 
 GoogleAdsException 
  
 gae 
 ) 
  
 { 
  
 System 
 . 
 out 
 . 
 printf 
 ( 
  
 "Unable to retrieve hierarchy for customer ID %d: %s%n" 
 , 
  
 customerIdToSearchFrom 
 , 
  
 gae 
 . 
 getGoogleAdsFailure 
 (). 
 getErrors 
 ( 
 0 
 ). 
 getMessage 
 ()); 
  
 return 
  
 null 
 ; 
  
 } 
  
 } 
  
 // The rootCustomerClient will be null if the account hierarchy was unable to be retrieved 
  
 // (e.g. the account is a test account or a client account with an incomplete billing setup). 
  
 // This method returns null in these cases to add the seedCustomerId to the list of 
  
 // customer IDs for which the account hierarchy could not be retrieved. 
  
 if 
  
 ( 
 rootCustomerClient 
  
 == 
  
 null 
 ) 
  
 { 
  
 return 
  
 null 
 ; 
  
 } 
  
 Map<CustomerClient 
 , 
  
 Multimap<Long 
 , 
  
 CustomerClient 
>>  
 customerClientToHierarchy 
  
 = 
  
 new 
  
 HashMap 
<> (); 
  
 customerClientToHierarchy 
 . 
 put 
 ( 
 rootCustomerClient 
 , 
  
 customerIdsToChildAccounts 
 ); 
  
 return 
  
 customerClientToHierarchy 
 ; 
  
 } 
  
 } 
  
 /** 
 * Retrieves a list of accessible customers with the provided set up credentials. 
 * 
 * @param googleAdsClient the Google Ads API client. 
 * @return a list of customer IDs. 
 */ 
  
 private 
  
 List<Long> 
  
 getAccessibleCustomers 
 ( 
 GoogleAdsClient 
  
 googleAdsClient 
 ) 
  
 { 
  
 List<Long> 
  
 seedCustomerIds 
  
 = 
  
 new 
  
 ArrayList 
<> (); 
  
 // Issues a request for listing all accessible customers by this authenticated Google account. 
  
 try 
  
 ( 
 CustomerServiceClient 
  
 customerServiceClient 
  
 = 
  
 googleAdsClient 
 . 
 getLatestVersion 
 (). 
 createCustomerServiceClient 
 ()) 
  
 { 
  
 ListAccessibleCustomersResponse 
  
 accessibleCustomers 
  
 = 
  
 customerServiceClient 
 . 
 listAccessibleCustomers 
 ( 
  
 ListAccessibleCustomersRequest 
 . 
 newBuilder 
 (). 
 build 
 ()); 
  
 System 
 . 
 out 
 . 
 println 
 ( 
  
 "No manager customer ID is specified. The example will print the " 
  
 + 
  
 "hierarchies of all accessible customer IDs:" 
 ); 
  
 for 
  
 ( 
 String 
  
 customerResourceName 
  
 : 
  
 accessibleCustomers 
 . 
 getResourceNamesList 
 ()) 
  
 { 
  
 Long 
  
 customer 
  
 = 
  
 Long 
 . 
 parseLong 
 ( 
 CustomerName 
 . 
 parse 
 ( 
 customerResourceName 
 ). 
 getCustomerId 
 ()); 
  
 System 
 . 
 out 
 . 
 println 
 ( 
 customer 
 ); 
  
 seedCustomerIds 
 . 
 add 
 ( 
 customer 
 ); 
  
 } 
  
 } 
  
 return 
  
 seedCustomerIds 
 ; 
  
 } 
  
 /** 
 * Prints the specified account's hierarchy using recursion. 
 * 
 * @param customerClient the customer client whose info will be printed and its child accounts 
 *     will be processed if it's a manager. 
 * @param customerIdsToChildAccounts a map containing the account hierarchy information. 
 * @param depth the current depth we are printing from in the account hierarchy. 
 */ 
  
 private 
  
 void 
  
 printAccountHierarchy 
 ( 
  
 CustomerClient 
  
 customerClient 
 , 
  
 Multimap<Long 
 , 
  
 CustomerClient 
>  
 customerIdsToChildAccounts 
 , 
  
 int 
  
 depth 
 ) 
  
 { 
  
 String 
  
 leadingSpace 
  
 = 
  
 " " 
 ; 
  
 if 
  
 ( 
 depth 
  
 == 
  
 0 
 ) 
  
 { 
  
 System 
 . 
 out 
 . 
 println 
 ( 
 "Customer ID (Descriptive Name, Currency Code, Time Zone" 
 ); 
  
 leadingSpace 
  
 = 
  
 "" 
 ; 
  
 } 
  
 else 
  
 { 
  
 System 
 . 
 out 
 . 
 println 
 ( 
 "|" 
 ); 
  
 } 
  
 System 
 . 
 out 
 . 
 print 
 ( 
 Strings 
 . 
 repeat 
 ( 
 "-" 
 , 
  
 depth 
  
 * 
  
 2 
 )); 
  
 long 
  
 customerId 
  
 = 
  
 customerClient 
 . 
 getId 
 (); 
  
 System 
 . 
 out 
 . 
 printf 
 ( 
  
 leadingSpace 
  
 + 
  
 "%d ('%s', '%s', '%s')%n" 
 , 
  
 customerId 
 , 
  
 customerClient 
 . 
 getDescriptiveName 
 (), 
  
 customerClient 
 . 
 getCurrencyCode 
 (), 
  
 customerClient 
 . 
 getTimeZone 
 ()); 
  
 // Recursively calls this function for all child accounts of customerClient if the current 
  
 // customer is a manager account. 
  
 for 
  
 ( 
 CustomerClient 
  
 childCustomer 
  
 : 
  
 customerIdsToChildAccounts 
 . 
 get 
 ( 
 customerId 
 )) 
  
 { 
  
 printAccountHierarchy 
 ( 
 childCustomer 
 , 
  
 customerIdsToChildAccounts 
 , 
  
 depth 
  
 + 
  
 1 
 ); 
  
 } 
  
 } 
 } 
  
  

C#

 // Copyright 2020 Google LLC 
 // 
 // Licensed under the Apache License, Version 2.0 (the "License"); 
 // you may not use this file except in compliance with the License. 
 // You may obtain a copy of the License at 
 // 
 //     http://www.apache.org/licenses/LICENSE-2.0 
 // 
 // Unless required by applicable law or agreed to in writing, software 
 // distributed under the License is distributed on an "AS IS" BASIS, 
 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
 // See the License for the specific language governing permissions and 
 // limitations under the License. 
 using 
  
 CommandLine 
 ; 
 using 
  
 Google.Ads.Gax.Examples 
 ; 
 using 
  
 Google.Ads.GoogleAds.Lib 
 ; 
 using 
  
 Google.Ads.GoogleAds.V21.Resources 
 ; 
 using 
  
 Google.Ads.GoogleAds.V21.Services 
 ; 
 using 
  
 Google.Api.Gax 
 ; 
 using 
  
 System 
 ; 
 using 
  
 System.Collections.Generic 
 ; 
 namespace 
  
 Google.Ads.GoogleAds.Examples.V21 
 { 
  
 /// <summary> 
  
 /// This example gets the account hierarchy of the specified manager account. If you don't 
  
 /// specify manager customer ID, the example will instead print the hierarchies of all 
  
 /// accessible customer accounts for your authenticated Google account. 
  
 /// Note that if the list of accessible customers for your authenticated Google account 
  
 /// includes accounts within the same hierarchy, this example will retrieve and print 
  
 /// the overlapping portions of the hierarchy for each accessible customer. 
  
 /// </summary> 
  
 public 
  
 class 
  
 GetAccountHierarchy 
  
 : 
  
 ExampleBase 
  
 { 
  
 /// <summary> 
  
 /// Command line options for running the <see cref="GetAccountHierarchy"/> example. 
  
 /// </summary> 
  
 public 
  
 class 
  
 Options 
  
 : 
  
 OptionsBase 
  
 { 
  
 /// <summary> 
  
 /// Optional manager account ID. If none provided, this method will instead list the 
  
 /// accounts accessible from the authenticated Google Ads account. 
  
 /// </summary> 
  
 [Option("managerCustomerId", Required = true, HelpText = 
 "Optional manager account ID. If none provided, this method will instead list the" + 
 " accounts accessible from the authenticated Google Ads account.")] 
  
 public 
  
 long? 
  
 ManagerCustomerId 
  
 { 
  
 get 
 ; 
  
 set 
 ; 
  
 } 
  
 /// <summary> 
  
 /// The login customer ID used to create the GoogleAdsClient. 
  
 /// </summary> 
  
 [Option("loginCustomerId", Required = false, HelpText = 
 "The login customer ID used to create the GoogleAdsClient.")] 
  
 public 
  
 long? 
  
 LoginCustomerId 
  
 { 
  
 get 
 ; 
  
 set 
 ; 
  
 } 
  
 } 
  
 /// <summary> 
  
 /// Main method, to run this code example as a standalone application. 
  
 /// </summary> 
  
 /// <param name="args">The command line arguments.</param> 
  
 public 
  
 static 
  
 void 
  
 Main 
 ( 
 string 
 [] 
  
 args 
 ) 
  
 { 
  
 Options 
  
 options 
  
 = 
  
 ExampleUtilities 
 . 
 ParseCommandLine<Options> 
 ( 
 args 
 ); 
  
 GetAccountHierarchy 
  
 codeExample 
  
 = 
  
 new 
  
 GetAccountHierarchy 
 (); 
  
 Console 
 . 
 WriteLine 
 ( 
 codeExample 
 . 
 Description 
 ); 
  
 codeExample 
 . 
 Run 
 ( 
 new 
  
 GoogleAdsClient 
 (), 
  
 options 
 . 
 ManagerCustomerId 
 , 
  
 options 
 . 
 LoginCustomerId 
 ); 
  
 } 
  
 /// <summary> 
  
 /// Returns a description about the code example. 
  
 /// </summary> 
  
 public 
  
 override 
  
 string 
  
 Description 
  
 = 
>  
 "This code example gets the account hierarchy of a specified manager account. If " 
  
 + 
  
 "you don't specify a manager customer ID, the example will instead print the " 
  
 + 
  
 "hierarchies of all accessible customer accounts for your authenticated " 
  
 + 
  
 "Google account." 
 ; 
  
 /// <summary> 
  
 /// Runs the code example. 
  
 /// </summary> 
  
 /// <param name="googleAdsClient">The Google Ads client instance.</param> 
  
 /// <param name="managerCustomerId">Optional manager account ID. If none provided, this method 
  
 /// will instead list the accounts accessible from the authenticated Google Ads account. 
  
 /// </param> 
  
 /// <param name="loginCustomerId">The login customer ID used to create the GoogleAdsClient. 
  
 /// </param> 
  
 public 
  
 void 
  
 Run 
 ( 
 GoogleAdsClient 
  
 googleAdsClient 
 , 
  
 long? 
  
 managerCustomerId 
  
 = 
  
 null 
 , 
  
 long? 
  
 loginCustomerId 
  
 = 
  
 null 
 ) 
  
 { 
  
 if 
  
 ( 
 loginCustomerId 
 . 
 HasValue 
 ) 
  
 { 
  
 googleAdsClient 
 . 
 Config 
 . 
 LoginCustomerId 
  
 = 
  
 loginCustomerId 
 . 
 Value 
 . 
 ToString 
 (); 
  
 } 
  
 GoogleAdsServiceClient 
  
 googleAdsServiceClient 
  
 = 
  
 googleAdsClient 
 . 
 GetService 
 ( 
 Services 
 . 
 V21 
 . 
 GoogleAdsService 
 ); 
  
 CustomerServiceClient 
  
 customerServiceClient 
  
 = 
  
 googleAdsClient 
 . 
 GetService 
 ( 
 Services 
 . 
 V21 
 . 
 CustomerService 
 ); 
  
 // List of Customer IDs to handle. 
  
 List<long> 
  
 seedCustomerIds 
  
 = 
  
 new 
  
 List<long> 
 (); 
  
 // If a Manager ID was provided in the customerId parameter, it will be the only ID 
  
 // in the list. Otherwise, we will issue a request for all customers accessible by 
  
 // this authenticated Google account. 
  
 if 
  
 ( 
 managerCustomerId 
 . 
 HasValue 
 ) 
  
 { 
  
 seedCustomerIds 
 . 
 Add 
 ( 
 managerCustomerId 
 . 
 Value 
 ); 
  
 } 
  
 else 
  
 { 
  
 Console 
 . 
 WriteLine 
 ( 
  
 "No manager customer ID is specified. The example will print the hierarchies" 
  
 + 
  
 " of all accessible customer IDs:" 
 ); 
  
 string 
 [] 
  
 customerResourceNames 
  
 = 
  
 customerServiceClient 
 . 
 ListAccessibleCustomers 
 (); 
  
 foreach 
  
 ( 
 string 
  
 customerResourceName 
  
 in 
  
 customerResourceNames 
 ) 
  
 { 
  
 CustomerName 
  
 customerName 
  
 = 
  
 CustomerName 
 . 
 Parse 
 ( 
 customerResourceName 
 ); 
  
 Console 
 . 
 WriteLine 
 ( 
 customerName 
 . 
 CustomerId 
 ); 
  
 seedCustomerIds 
 . 
 Add 
 ( 
 long 
 . 
 Parse 
 ( 
 customerName 
 . 
 CustomerId 
 )); 
  
 } 
  
 Console 
 . 
 WriteLine 
 (); 
  
 } 
  
 // Create a query that retrieves all child accounts of the manager specified in 
  
 // search calls below. 
  
 const 
  
 string 
  
 query 
  
 = 
  
 @"SELECT 
 customer_client.client_customer, 
 customer_client.level, 
 customer_client.manager, 
 customer_client.descriptive_name, 
 customer_client.currency_code, 
 customer_client.time_zone, 
 customer_client.id 
 FROM customer_client 
 WHERE 
 customer_client.level <= 1" 
 ; 
  
 // Perform a breadth-first search to build a Dictionary that maps managers to their 
  
 // child accounts. 
  
 Dictionary<long 
 , 
  
 List<CustomerClient> 
>  
 customerIdsToChildAccounts 
  
 = 
  
 new 
  
 Dictionary<long 
 , 
  
 List<CustomerClient> 
> (); 
  
 foreach 
  
 ( 
 long 
  
 seedCustomerId 
  
 in 
  
 seedCustomerIds 
 ) 
  
 { 
  
 Queue<long> 
  
 unprocessedCustomerIds 
  
 = 
  
 new 
  
 Queue<long> 
 (); 
  
 unprocessedCustomerIds 
 . 
 Enqueue 
 ( 
 seedCustomerId 
 ); 
  
 CustomerClient 
  
 rootCustomerClient 
  
 = 
  
 null 
 ; 
  
 while 
  
 ( 
 unprocessedCustomerIds 
 . 
 Count 
 > 
 0 
 ) 
  
 { 
  
 managerCustomerId 
  
 = 
  
 unprocessedCustomerIds 
 . 
 Dequeue 
 (); 
  
 PagedEnumerable<SearchGoogleAdsResponse 
 , 
  
 GoogleAdsRow 
>  
 response 
  
 = 
  
 googleAdsServiceClient 
 . 
 Search 
 ( 
  
 managerCustomerId 
 . 
 ToString 
 (), 
  
 query 
  
 ); 
  
 // Iterate over all rows in all pages to get all customer clients under the 
  
 // specified customer's hierarchy. 
  
 foreach 
  
 ( 
 GoogleAdsRow 
  
 googleAdsRow 
  
 in 
  
 response 
 ) 
  
 { 
  
 CustomerClient 
  
 customerClient 
  
 = 
  
 googleAdsRow 
 . 
 CustomerClient 
 ; 
  
 // The customer client that with level 0 is the specified customer. 
  
 if 
  
 ( 
 customerClient 
 . 
 Level 
  
 == 
  
 0 
 ) 
  
 { 
  
 if 
  
 ( 
 rootCustomerClient 
  
 == 
  
 null 
 ) 
  
 { 
  
 rootCustomerClient 
  
 = 
  
 customerClient 
 ; 
  
 } 
  
 continue 
 ; 
  
 } 
  
 // For all level-1 (direct child) accounts that are a manager account, 
  
 // the above query will be run against them to create a Dictionary of 
  
 // managers mapped to their child accounts for printing the hierarchy 
  
 // afterwards. 
  
 if 
  
 ( 
 ! 
 customerIdsToChildAccounts 
 . 
 ContainsKey 
 ( 
 managerCustomerId 
 . 
 Value 
 )) 
  
 customerIdsToChildAccounts 
 . 
 Add 
 ( 
 managerCustomerId 
 . 
 Value 
 , 
  
 new 
  
 List<CustomerClient> 
 ()); 
  
 customerIdsToChildAccounts 
 [ 
 managerCustomerId 
 . 
 Value 
 ]. 
 Add 
 ( 
 customerClient 
 ); 
  
 if 
  
 ( 
 customerClient 
 . 
 Manager 
 ) 
  
 // A customer can be managed by multiple managers, so to prevent 
  
 // visiting the same customer many times, we need to check if it's 
  
 // already in the Dictionary. 
  
 if 
  
 ( 
 ! 
 customerIdsToChildAccounts 
 . 
 ContainsKey 
 ( 
 customerClient 
 . 
 Id 
 ) 
  
&&  
 customerClient 
 . 
 Level 
  
 == 
  
 1 
 ) 
  
 unprocessedCustomerIds 
 . 
 Enqueue 
 ( 
 customerClient 
 . 
 Id 
 ); 
  
 } 
  
 } 
  
 if 
  
 ( 
 rootCustomerClient 
  
 != 
  
 null 
 ) 
  
 { 
  
 Console 
 . 
 WriteLine 
 ( 
 "The hierarchy of customer ID {0} is printed below:" 
 , 
  
 rootCustomerClient 
 . 
 Id 
 ); 
  
 PrintAccountHierarchy 
 ( 
 rootCustomerClient 
 , 
  
 customerIdsToChildAccounts 
 , 
  
 0 
 ); 
  
 Console 
 . 
 WriteLine 
 (); 
  
 } 
  
 else 
  
 { 
  
 Console 
 . 
 WriteLine 
 ( 
  
 "Customer ID {0} is likely a test account, so its customer client " 
  
 + 
  
 " information cannot be retrieved." 
 , 
  
 managerCustomerId 
 ); 
  
 } 
  
 } 
  
 } 
  
 /// <summary> 
  
 /// Prints the specified account's hierarchy using recursion. 
  
 /// <param name="customerClient"> 
  
 /// the customer client whose info will be printed and 
  
 /// its child accounts will be processed if it's a manager 
  
 /// </param> 
  
 /// <param name="customerIdsToChildAccounts"> a Dictionary mapping customer IDs to 
  
 ///     child accounts</param> 
  
 /// <param name="depth"> the current integer depth we are printing from in the 
  
 ///     account hierarchy</param> 
  
 /// </summary> 
  
 private 
  
 void 
  
 PrintAccountHierarchy 
 ( 
 CustomerClient 
  
 customerClient 
 , 
  
 Dictionary<long 
 , 
  
 List<CustomerClient> 
>  
 customerIdsToChildAccounts 
 , 
  
 int 
  
 depth 
 ) 
  
 { 
  
 if 
  
 ( 
 depth 
  
 == 
  
 0 
 ) 
  
 Console 
 . 
 WriteLine 
 ( 
 "Customer ID (Descriptive Name, Currency Code, Time Zone)" 
 ); 
  
 long 
  
 customerId 
  
 = 
  
 customerClient 
 . 
 Id 
 ; 
  
 Console 
 . 
 Write 
 ( 
 new 
  
 string 
 ( 
 '-' 
 , 
  
 depth 
  
 * 
  
 2 
 )); 
  
 Console 
 . 
 WriteLine 
 ( 
 "{0} ({1}, {2}, {3})" 
 , 
  
 customerId 
 , 
  
 customerClient 
 . 
 DescriptiveName 
 , 
  
 customerClient 
 . 
 CurrencyCode 
 , 
  
 customerClient 
 . 
 TimeZone 
 ); 
  
 // Recursively call this function for all child accounts of $customerClient. 
  
 if 
  
 ( 
 customerIdsToChildAccounts 
 . 
 ContainsKey 
 ( 
 customerId 
 )) 
  
 foreach 
  
 ( 
 CustomerClient 
  
 childAccount 
  
 in 
  
 customerIdsToChildAccounts 
 [ 
 customerId 
 ]) 
  
 PrintAccountHierarchy 
 ( 
 childAccount 
 , 
  
 customerIdsToChildAccounts 
 , 
  
 depth 
  
 + 
  
 1 
 ); 
  
 } 
  
 } 
 } 
  
  

PHP

< ?php 
 /** 
 * Copyright 2019 Google LLC 
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); 
 * you may not use this file except in compliance with the License. 
 * You may obtain a copy of the License at 
 * 
 *     https://www.apache.org/licenses/LICENSE-2.0 
 * 
 * Unless required by applicable law or agreed to in writing, software 
 * distributed under the License is distributed on an "AS IS" BASIS, 
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
 * See the License for the specific language governing permissions and 
 * limitations under the License. 
 */ 
 namespace Google\Ads\GoogleAds\Examples\AccountManagement; 
 require __DIR__ . '/../../vendor/autoload.php'; 
 use GetOpt\GetOpt; 
 use Google\Ads\GoogleAds\Examples\Utils\ArgumentNames; 
 use Google\Ads\GoogleAds\Examples\Utils\ArgumentParser; 
 use Google\Ads\GoogleAds\Lib\OAuth2TokenBuilder; 
 use Google\Ads\GoogleAds\Lib\V21\GoogleAdsClient; 
 use Google\Ads\GoogleAds\Lib\V21\GoogleAdsClientBuilder; 
 use Google\Ads\GoogleAds\Lib\V21\GoogleAdsException; 
 use Google\Ads\GoogleAds\Lib\V21\GoogleAdsServerStreamDecorator; 
 use Google\Ads\GoogleAds\V21\Errors\GoogleAdsError; 
 use Google\Ads\GoogleAds\V21\Resources\CustomerClient; 
 use Google\Ads\GoogleAds\V21\Services\CustomerServiceClient; 
 use Google\Ads\GoogleAds\V21\Services\GoogleAdsRow; 
 use Google\Ads\GoogleAds\V21\Services\ListAccessibleCustomersRequest; 
 use Google\Ads\GoogleAds\V21\Services\SearchGoogleAdsStreamRequest; 
 use Google\ApiCore\ApiException; 
 /** 
 * Gets the account hierarchy of the specified manager customer ID and login customer ID. If you 
 * don't specify them, the example will instead print the hierarchies of all accessible customer 
 * accounts for your authenticated Google account. Note that if the list of accessible customers 
 * for your authenticated Google account includes accounts within the same hierarchy, this example 
 * will retrieve and print the overlapping portions of the hierarchy for each accessible customer. 
 */ 
 class GetAccountHierarchy 
 { 
 // Optional: You may pass the manager customer ID on the command line or specify it here. If 
 // neither are set, a null value will be passed to the runExample() method, and the example 
 // will print the hierarchies of all accessible customer IDs. 
 private const MANAGER_CUSTOMER_ID = null; 
 // Optional: You may pass the login customer ID on the command line or specify it here if and 
 // only if the manager customer ID is set. If the login customer ID is set neither on the 
 // command line nor below, a null value will be passed to the runExample() method, and the 
 // example will use each accessible customer ID as the login customer ID. 
 private const LOGIN_CUSTOMER_ID = null; 
 // Stores the mapping from the root customer IDs (the ones that will be used as a start point 
 // for printing each hierarchy) to their `CustomerClient` objects. 
 private static array $rootCustomerClients = []; 
 public static function main() 
 { 
 // Either pass the required parameters for this example on the command line, or insert them 
 // into the constants above. 
 $options = (new ArgumentParser())->parseCommandArguments([ 
 ArgumentNames::MANAGER_CUSTOMER_ID => GetOpt::OPTIONAL_ARGUMENT, 
 ArgumentNames::LOGIN_CUSTOMER_ID => GetOpt::OPTIONAL_ARGUMENT 
 ]); 
 $managerCustomerId = 
 $options[ArgumentNames::MANAGER_CUSTOMER_ID] ?: self::MANAGER_CUSTOMER_ID; 
 $loginCustomerId = 
 $options[ArgumentNames::LOGIN_CUSTOMER_ID] ?: self::LOGIN_CUSTOMER_ID; 
 if ($managerCustomerId xor $loginCustomerId) { 
 throw new \InvalidArgumentException( 
 'Both the manager customer ID and login customer ID must be provided together, ' 
 . 'or they must both be null.' 
 ); 
 } 
 // Generate a refreshable OAuth2 credential for authentication. 
 $oAuth2Credential = (new OAuth2TokenBuilder())->fromFile()->build(); 
 // Construct a Google Ads client configured from a properties file and the 
 // OAuth2 credentials above. 
 $googleAdsClient = (new GoogleAdsClientBuilder())->fromFile() 
 ->withOAuth2Credential($oAuth2Credential) 
 ->build(); 
 try { 
 self::runExample($googleAdsClient, $managerCustomerId, $loginCustomerId); 
 } catch (GoogleAdsException $googleAdsException) { 
 printf( 
 "Request with ID '%s' has failed.%sGoogle Ads failure details:%s", 
 $googleAdsException->getRequestId(), 
 PHP_EOL, 
 PHP_EOL 
 ); 
 foreach ($googleAdsException->getGoogleAdsFailure()->getErrors() as $error) { 
 /** @var GoogleAdsError $error */ 
 printf( 
 "\t%s: %s%s", 
 $error->getErrorCode()->getErrorCode(), 
 $error->getMessage(), 
 PHP_EOL 
 ); 
 } 
 exit(1); 
 } catch (ApiException $apiException) { 
 printf( 
 "ApiException was thrown with message '%s'.%s", 
 $apiException->getMessage(), 
 PHP_EOL 
 ); 
 exit(1); 
 } 
 } 
 /** 
 * Runs the example. 
 * 
 * @param GoogleAdsClient $googleAdsClient the Google Ads API client 
 * @param int|null $managerCustomerId the manager customer ID 
 * @param int|null $loginCustomerId the login customer ID 
 */ 
 public static function runExample( 
 GoogleAdsClient $googleAdsClient, 
 ?int $managerCustomerId, 
 ?int $loginCustomerId 
 ) { 
 $rootCustomerIds = []; 
 if (is_null($managerCustomerId)) { 
 // We will get the account hierarchies for all accessible customers. 
 $rootCustomerIds = self::getAccessibleCustomers($googleAdsClient); 
 } else { 
 // We will get only the hierarchy for the provided manager customer ID when it's 
 // provided. 
 $rootCustomerIds[] = $managerCustomerId; 
 } 
 $allHierarchies = []; 
 $accountsWithNoInfo = []; 
 // Constructs a map of account hierarchies. 
 foreach ($rootCustomerIds as $rootCustomerId) { 
 $customerClientToHierarchy = 
 self::createCustomerClientToHierarchy($loginCustomerId, $rootCustomerId); 
 if (is_null($customerClientToHierarchy)) { 
 $accountsWithNoInfo[] = $rootCustomerId; 
 } else { 
 $allHierarchies += $customerClientToHierarchy; 
 } 
 } 
 // Prints the IDs of any accounts that did not produce hierarchy information. 
 if (!empty($accountsWithNoInfo)) { 
 print 
 'Unable to retrieve information for the following accounts which are likely ' 
 . 'either test accounts or accounts with setup issues. Please check the logs for ' 
 . 'details:' . PHP_EOL; 
 foreach ($accountsWithNoInfo as $accountId) { 
 print $accountId . PHP_EOL; 
 } 
 print PHP_EOL; 
 } 
 // Prints the hierarchy information for all accounts for which there is hierarchy info 
 // available. 
 foreach ($allHierarchies as $rootCustomerId => $customerIdsToChildAccounts) { 
 printf( 
 "The hierarchy of customer ID %d is printed below:%s", 
 $rootCustomerId, 
 PHP_EOL 
 ); 
 self::printAccountHierarchy( 
 self::$rootCustomerClients[$rootCustomerId], 
 $customerIdsToChildAccounts, 
 0 
 ); 
 print PHP_EOL; 
 } 
 } 
 /** 
 * Creates a map between a customer client and each of its managers' mappings. 
 * 
 * @param int|null $loginCustomerId the login customer ID used to create the GoogleAdsClient 
 * @param int $rootCustomerId the ID of the customer at the root of the tree 
 * @return array|null a map between a customer client and each of its managers' mappings if the 
 *     account hierarchy can be retrieved. If the account hierarchy cannot be retrieved, returns 
 *     null 
 */ 
 private static function createCustomerClientToHierarchy( 
 ?int $loginCustomerId, 
 int $rootCustomerId 
 ): ?array { 
 // Creates a GoogleAdsClient with the specified login customer ID. See 
 // https://developers.google.com/google-ads/api/docs/concepts/call-structure#cid for more 
 // information. 
 // Generate a refreshable OAuth2 credential for authentication. 
 $oAuth2Credential = (new OAuth2TokenBuilder())->fromFile()->build(); 
 // Construct a Google Ads client configured from a properties file and the 
 // OAuth2 credentials above. 
 $googleAdsClient = (new GoogleAdsClientBuilder())->fromFile() 
 ->withOAuth2Credential($oAuth2Credential) 
 ->withLoginCustomerId($loginCustomerId ?? $rootCustomerId) 
 ->build(); 
 // Creates the Google Ads Service client. 
 $googleAdsServiceClient = $googleAdsClient->getGoogleAdsServiceClient(); 
 // Creates a query that retrieves all child accounts of the manager specified in search 
 // calls below. 
 $query = 'SELECT customer_client.client_customer, customer_client.level,' 
 . ' customer_client.manager, customer_client.descriptive_name,' 
 . ' customer_client.currency_code, customer_client.time_zone,' 
 . ' customer_client.id FROM customer_client WHERE customer_client.level <= 1'; 
 $rootCustomerClient = null; 
 // Adds the root customer ID to the list of IDs to be processed. 
 $managerCustomerIdsToSearch = [$rootCustomerId]; 
 // Performs a breadth-first search algorithm to build an associative array mapping 
 // managers to their child accounts ($customerIdsToChildAccounts). 
 $customerIdsToChildAccounts = []; 
 while (!empty($managerCustomerIdsToSearch)) { 
 $customerIdToSearch = array_shift($managerCustomerIdsToSearch); 
 // Issues a search request. 
 /** @var GoogleAdsServerStreamDecorator $stream */ 
 $stream = $googleAdsServiceClient->searchStream(SearchGoogleAdsStreamRequest::build( 
 $customerIdToSearch, 
 $query 
 )); 
 // Iterates over all elements to get all customer clients under the specified customer's 
 // hierarchy. 
 foreach ($stream->iterateAllElements() as $googleAdsRow) { 
 /** @var GoogleAdsRow $googleAdsRow */ 
 $customerClient = $googleAdsRow->getCustomerClient(); 
 // Gets the CustomerClient object for the root customer in the tree. 
 if ($customerClient->getId() === $rootCustomerId) { 
 $rootCustomerClient = $customerClient; 
 self::$rootCustomerClients[$rootCustomerId] = $rootCustomerClient; 
 } 
 // The steps below map parent and children accounts. Continue here so that managers 
 // accounts exclude themselves from the list of their children accounts. 
 if ($customerClient->getId() === $customerIdToSearch) { 
 continue; 
 } 
 // For all level-1 (direct child) accounts that are a manager account, the above 
 // query will be run against them to create an associative array of managers to 
 // their child accounts for printing the hierarchy afterwards. 
 $customerIdsToChildAccounts[$customerIdToSearch][] = $customerClient; 
 // Checks if the child account is a manager itself so that it can later be processed 
 // and added to the map if it hasn't been already. 
 if ($customerClient->getManager()) { 
 // A customer can be managed by multiple managers, so to prevent visiting 
 // the same customer multiple times, we need to check if it's already in the 
 // map. 
 $alreadyVisited = array_key_exists( 
 $customerClient->getId(), 
 $customerIdsToChildAccounts 
 ); 
 if (!$alreadyVisited && $customerClient->getLevel() === 1) { 
 array_push($managerCustomerIdsToSearch, $customerClient->getId()); 
 } 
 } 
 } 
 } 
 return is_null($rootCustomerClient) ? null 
 : [$rootCustomerClient->getId() => $customerIdsToChildAccounts]; 
 } 
 /** 
 * Retrieves a list of accessible customers with the provided set up credentials. 
 * 
 * @param GoogleAdsClient $googleAdsClient the Google Ads API client 
 * @return int[] the list of customer IDs 
 */ 
 private static function getAccessibleCustomers(GoogleAdsClient $googleAdsClient): array 
 { 
 $accessibleCustomerIds = []; 
 // Issues a request for listing all customers accessible by this authenticated Google 
 // account. 
 $customerServiceClient = $googleAdsClient->getCustomerServiceClient(); 
 $accessibleCustomers = 
 $customerServiceClient->listAccessibleCustomers(new ListAccessibleCustomersRequest()); 
 print 'No manager customer ID is specified. The example will print the hierarchies of' 
 . ' all accessible customer IDs:' . PHP_EOL; 
 foreach ($accessibleCustomers->getResourceNames() as $customerResourceName) { 
 $customer = CustomerServiceClient::parseName($customerResourceName)['customer_id']; 
 print $customer . PHP_EOL; 
 $accessibleCustomerIds[] = intval($customer); 
 } 
 print PHP_EOL; 
 return $accessibleCustomerIds; 
 } 
 /** 
 * Prints the specified account's hierarchy using recursion. 
 * 
 * @param CustomerClient $customerClient the customer client whose info will be printed and 
 *     its child accounts will be processed if it's a manager 
 * @param array $customerIdsToChildAccounts a map from customer IDs to child 
 *     accounts 
 * @param int $depth the current depth we are printing from in the 
 *     account hierarchy 
 */ 
 private static function printAccountHierarchy( 
 CustomerClient $customerClient, 
 array $customerIdsToChildAccounts, 
 int $depth 
 ) { 
 if ($depth === 0) { 
 print 'Customer ID (Descriptive Name, Currency Code, Time Zone)' . PHP_EOL; 
 } 
 $customerId = $customerClient->getId(); 
 print str_repeat('-', $depth * 2); 
 printf( 
 " %d ('%s', '%s', '%s')%s", 
 $customerId, 
 $customerClient->getDescriptiveName(), 
 $customerClient->getCurrencyCode(), 
 $customerClient->getTimeZone(), 
 PHP_EOL 
 ); 
 // Recursively call this function for all child accounts of $customerClient. 
 if (array_key_exists($customerId, $customerIdsToChildAccounts)) { 
 foreach ($customerIdsToChildAccounts[$customerId] as $childAccount) { 
 self::printAccountHierarchy($childAccount, $customerIdsToChildAccounts, $depth + 1); 
 } 
 } 
 } 
 } 
 GetAccountHierarchy::main(); 
  
  

Python

 #!/usr/bin/env python 
 # Copyright 2020 Google LLC 
 # 
 # Licensed under the Apache License, Version 2.0 (the "License"); 
 # you may not use this file except in compliance with the License. 
 # You may obtain a copy of the License at 
 # 
 #     https://www.apache.org/licenses/LICENSE-2.0 
 # 
 # Unless required by applicable law or agreed to in writing, software 
 # distributed under the License is distributed on an "AS IS" BASIS, 
 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
 # See the License for the specific language governing permissions and 
 # limitations under the License. 
 """Gets the account hierarchy of the given MCC and login customer ID. 
 If you don't specify manager ID and login customer ID, the example will instead 
 print the hierarchies of all accessible customer accounts for your 
 authenticated Google account. Note that if the list of accessible customers for 
 your authenticated Google account includes accounts within the same hierarchy, 
 this example will retrieve and print the overlapping portions of the hierarchy 
 for each accessible customer. 
 """ 
 import 
  
 argparse 
 import 
  
 sys 
 from 
  
 typing 
  
 import 
 Optional 
 , 
 List 
 , 
 Dict 
 from 
  
 google.ads.googleads.client 
  
 import 
 GoogleAdsClient 
 from 
  
 google.ads.googleads.errors 
  
 import 
 GoogleAdsException 
 from 
  
 google.ads.googleads.v21.services.services.google_ads_service.client 
  
 import 
 ( 
 GoogleAdsServiceClient 
 , 
 ) 
 from 
  
 google.ads.googleads.v21.services.services.customer_service.client 
  
 import 
 ( 
 CustomerServiceClient 
 , 
 ) 
 from 
  
 google.ads.googleads.v21.resources.types.customer_client 
  
 import 
 ( 
 CustomerClient 
 , 
 ) 
 from 
  
 google.ads.googleads.v21.services.types.google_ads_service 
  
 import 
 ( 
 SearchPagedResponse 
 , 
 GoogleAdsRow 
 , 
 ) 
 # ListAccessibleCustomersResponse is not directly used for a variable type, 
 # but its attribute .resource_names is used, which is List[str]. 
 def 
  
 main 
 ( 
 client 
 : 
 GoogleAdsClient 
 , 
 login_customer_id 
 : 
 Optional 
 [ 
 str 
 ] 
 = 
 None 
 ) 
 - 
> None 
 : 
  
 """Gets the account hierarchy of the given MCC and login customer ID. 
 Args: 
 client: The Google Ads client. 
 login_customer_id: Optional manager account ID. If none provided, this 
 method will instead list the accounts accessible from the 
 authenticated Google Ads account. 
 """ 
 # Gets instances of the GoogleAdsService and CustomerService clients. 
 googleads_service 
 : 
 GoogleAdsServiceClient 
 = 
 client 
 . 
 get_service 
 ( 
 "GoogleAdsService" 
 ) 
 customer_service 
 : 
 CustomerServiceClient 
 = 
 client 
 . 
 get_service 
 ( 
 "CustomerService" 
 ) 
 # A collection of customer IDs to handle. 
 seed_customer_ids 
 : 
 List 
 [ 
 str 
 ] 
 = 
 [] 
 # Creates a query that retrieves all child accounts of the manager 
 # specified in search calls below. 
 query 
 = 
 """ 
 SELECT 
 customer_client.client_customer, 
 customer_client.level, 
 customer_client.manager, 
 customer_client.descriptive_name, 
 customer_client.currency_code, 
 customer_client.time_zone, 
 customer_client.id 
 FROM customer_client 
 WHERE customer_client.level <= 1""" 
 # If a Manager ID was provided in the customerId parameter, it will be 
 # the only ID in the list. Otherwise, we will issue a request for all 
 # customers accessible by this authenticated Google account. 
 if 
 login_customer_id 
 is 
 not 
 None 
 : 
 # Ensure login_customer_id is treated as a string for this list. 
 seed_customer_ids 
 = 
 [ 
 login_customer_id 
 ] 
 else 
 : 
 print 
 ( 
 "No manager ID is specified. The example will print the " 
 "hierarchies of all accessible customer IDs." 
 ) 
 customer_resource_names 
 : 
 List 
 [ 
 str 
 ] 
 = 
 ( 
 customer_service 
 . 
 list_accessible_customers 
 () 
 . 
 resource_names 
 ) 
 for 
 customer_resource_name 
 in 
 customer_resource_names 
 : 
 # customer_id here is a string as returned by parse_customer_path 
 customer_id_from_parse 
 : 
 str 
 = 
 googleads_service 
 . 
 parse_customer_path 
 ( 
 customer_resource_name 
 )[ 
 "customer_id" 
 ] 
 print 
 ( 
 customer_id_from_parse 
 ) 
 seed_customer_ids 
 . 
 append 
 ( 
 customer_id_from_parse 
 ) 
 for 
 ( 
 seed_customer_id_str 
 ) 
 in 
 seed_customer_ids 
 : 
 # seed_customer_id_str is a string 
 # Performs a breadth-first search to build a Dictionary that maps 
 # managers to their child accounts (customerIdsToChildAccounts). 
 # unprocessed_customer_ids should store integers. 
 unprocessed_customer_ids 
 : 
 List 
 [ 
 int 
 ] 
 = 
 [ 
 int 
 ( 
 seed_customer_id_str 
 )] 
 customer_ids_to_child_accounts 
 : 
 Dict 
 [ 
 int 
 , 
 List 
 [ 
 CustomerClient 
 ]] 
 = 
 dict 
 () 
 root_customer_client 
 : 
 CustomerClient 
 | 
 None 
 = 
 None 
 while 
 unprocessed_customer_ids 
 : 
 customer_id_loop 
 : 
 int 
 = 
 unprocessed_customer_ids 
 . 
 pop 
 ( 
 0 
 ) 
 # customer_id_loop is an int 
 # The search method expects customer_id to be a string. 
 response 
 : 
 SearchPagedResponse 
 = 
 googleads_service 
 . 
 search 
 ( 
 customer_id 
 = 
 str 
 ( 
 customer_id_loop 
 ), 
 query 
 = 
 query 
 ) 
 # Iterates over all rows in all pages to get all customer 
 # clients under the specified customer's hierarchy. 
 googleads_row 
 : 
 GoogleAdsRow 
 for 
 googleads_row 
 in 
 response 
 : 
 customer_client_loop_var 
 : 
 CustomerClient 
 = 
 ( 
 googleads_row 
 . 
 customer_client 
 ) 
 # The customer client that with level 0 is the specified 
 # customer. 
 if 
 customer_client_loop_var 
 . 
 level 
 == 
 0 
 : 
 if 
 root_customer_client 
 is 
 None 
 : 
 root_customer_client 
 = 
 customer_client_loop_var 
 continue 
 # For all level-1 (direct child) accounts that are a 
 # manager account, the above query will be run against them 
 # to create a Dictionary of managers mapped to their child 
 # accounts for printing the hierarchy afterwards. 
 if 
 customer_id_loop 
 not 
 in 
 customer_ids_to_child_accounts 
 : 
 customer_ids_to_child_accounts 
 [ 
 customer_id_loop 
 ] 
 = 
 [] 
 customer_ids_to_child_accounts 
 [ 
 customer_id_loop 
 ] 
 . 
 append 
 ( 
 customer_client_loop_var 
 ) 
 if 
 customer_client_loop_var 
 . 
 manager 
 : 
 # A customer can be managed by multiple managers, so to 
 # prevent visiting the same customer many times, we 
 # need to check if it's already in the Dictionary. 
 # Assuming customer_client_loop_var.id is an int 
 if 
 ( 
 customer_client_loop_var 
 . 
 id 
 not 
 in 
 customer_ids_to_child_accounts 
 and 
 customer_client_loop_var 
 . 
 level 
 == 
 1 
 ): 
 unprocessed_customer_ids 
 . 
 append 
 ( 
 customer_client_loop_var 
 . 
 id 
 ) 
 if 
 root_customer_client 
 is 
 not 
 None 
 : 
 print 
 ( 
 "The hierarchy of customer ID " 
 f 
 " 
 { 
 root_customer_client 
 . 
 id 
 } 
 is printed below:" 
 ) 
 print_account_hierarchy 
 ( 
 root_customer_client 
 , 
 customer_ids_to_child_accounts 
 , 
 0 
 ) 
 else 
 : 
 print 
 ( 
 f 
 "Customer ID 
 { 
 login_customer_id 
 } 
 is likely a test " 
 "account, so its customer client information cannot be " 
 "retrieved." 
 ) 
 def 
  
 print_account_hierarchy 
 ( 
 customer_client 
 : 
 CustomerClient 
 , 
 customer_ids_to_child_accounts 
 : 
 Dict 
 [ 
 int 
 , 
 List 
 [ 
 CustomerClient 
 ]], 
 depth 
 : 
 int 
 , 
 ) 
 - 
> None 
 : 
  
 """Prints the specified account's hierarchy using recursion. 
 Args: 
 customer_client: The customer client whose info will be printed; its 
 child accounts will be processed if it's a manager. 
 customer_ids_to_child_accounts: A dictionary mapping customer IDs to 
 child accounts. 
 depth: The current integer depth we are printing from in the account 
 hierarchy. 
 """ 
 if 
 depth 
 == 
 0 
 : 
 print 
 ( 
 "Customer ID (Descriptive Name, Currency Code, Time Zone)" 
 ) 
 # Assuming customer_client.id is an int based on previous analysis for keys in customer_ids_to_child_accounts 
 customer_id_print 
 : 
 int 
 = 
 customer_client 
 . 
 id 
 print 
 ( 
 "-" 
 * 
 ( 
 depth 
 * 
 2 
 ), 
 end 
 = 
 "" 
 ) 
 print 
 ( 
 f 
 " 
 { 
 customer_id_print 
 } 
 ( 
 { 
 customer_client 
 . 
 descriptive_name 
 } 
 , " 
 f 
 " 
 { 
 customer_client 
 . 
 currency_code 
 } 
 , " 
 f 
 " 
 { 
 customer_client 
 . 
 time_zone 
 } 
 )" 
 ) 
 # Recursively call this function for all child accounts of customer_client. 
 if 
 customer_id_print 
 in 
 customer_ids_to_child_accounts 
 : 
 child_account 
 : 
 CustomerClient 
 for 
 child_account 
 in 
 customer_ids_to_child_accounts 
 [ 
 customer_id_print 
 ]: 
 print_account_hierarchy 
 ( 
 child_account 
 , 
 customer_ids_to_child_accounts 
 , 
 depth 
 + 
 1 
 ) 
 if 
 __name__ 
 == 
 "__main__" 
 : 
 parser 
 = 
 argparse 
 . 
 ArgumentParser 
 ( 
 description 
 = 
 "This example gets the account hierarchy of the specified " 
 "manager account and login customer ID." 
 ) 
 # The following argument(s) should be provided to run the example. 
 parser 
 . 
 add_argument 
 ( 
 "-l" 
 , 
 "--login_customer_id" 
 , 
 "--manager_customer_id" 
 , 
 type 
 = 
 str 
 , 
 required 
 = 
 False 
 , 
 help 
 = 
 "Optional manager " 
 "account ID. If none provided, the example will " 
 "instead list the accounts accessible from the " 
 "authenticated Google Ads account." 
 , 
 ) 
 args 
 = 
 parser 
 . 
 parse_args 
 () 
 # GoogleAdsClient will read the google-ads.yaml configuration file in the 
 # home directory if none is specified. 
 googleads_client 
 = 
 GoogleAdsClient 
 . 
 load_from_storage 
 ( 
 version 
 = 
 "v21" 
 ) 
 try 
 : 
 main 
 ( 
 googleads_client 
 , 
 args 
 . 
 login_customer_id 
 ) 
 except 
 GoogleAdsException 
 as 
 ex 
 : 
 print 
 ( 
 f 
 'Request with ID " 
 { 
 ex 
 . 
 request_id 
 } 
 " failed with status ' 
 f 
 '" 
 { 
 ex 
 . 
 error 
 . 
 code 
 () 
 . 
 name 
 } 
 " and includes the following errors:' 
 ) 
 for 
 error 
 in 
 ex 
 . 
 failure 
 . 
 errors 
 : 
 print 
 ( 
 f 
 ' 
 \t 
 Error with message " 
 { 
 error 
 . 
 message 
 } 
 ".' 
 ) 
 if 
 error 
 . 
 location 
 : 
 for 
 field_path_element 
 in 
 error 
 . 
 location 
 . 
 field_path_elements 
 : 
 print 
 ( 
 f 
 " 
 \t\t 
 On field: 
 { 
 field_path_element 
 . 
 field_name 
 } 
 " 
 ) 
 sys 
 . 
 exit 
 ( 
 1 
 ) 
  

Ruby

 #!/usr/bin/env ruby 
 # Encoding: utf-8 
 # 
 # Copyright 2020 Google LLC 
 # 
 # Licensed under the Apache License, Version 2.0 (the "License"); 
 # you may not use this file except in compliance with the License. 
 # You may obtain a copy of the License at 
 # 
 #     https://www.apache.org/licenses/LICENSE-2.0 
 # 
 # Unless required by applicable law or agreed to in writing, software 
 # distributed under the License is distributed on an "AS IS" BASIS, 
 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
 # See the License for the specific language governing permissions and 
 # limitations under the License. 
 # 
 # This example gets the account hierarchy of the specified manager account. 
 # If you don't specify manager customer ID, the example will instead print the 
 # hierarchies of all accessible customer accounts for your authenticated 
 # Google account. 
 # Note that if the list of accessible customers for your authenticated Google 
 # account includes accounts within the same hierarchy, this example will 
 # retrieve and print the overlapping portions of the hierarchy for each 
 # accessible customer. 
 require 
  
 'optparse' 
 require 
  
 'google/ads/google_ads' 
 require 
  
 'thread' 
 def 
  
 get_account_hierarchy 
 ( 
 manager_customer_id 
 , 
  
 login_customer_id 
 ) 
  
 # GoogleAdsClient will read a config file from 
  
 # ENV['HOME']/google_ads_config.rb when called without parameters 
  
 client 
  
 = 
  
 Google 
 :: 
 Ads 
 :: 
 GoogleAds 
 :: 
 GoogleAdsClient 
 . 
 new 
  
 # Set the specified login customer ID. 
  
 client 
 . 
 configure 
  
 do 
  
 | 
 config 
 | 
  
 if 
  
 login_customer_id 
  
 config 
 . 
 login_customer_id 
  
 = 
  
 login_customer_id 
 . 
 to_i 
  
 elsif 
  
 manager_customer_id 
  
 config 
 . 
 login_customer_id 
  
 = 
  
 manager_customer_id 
 . 
 to_i 
  
 end 
  
 end 
  
 google_ads_service 
  
 = 
  
 client 
 . 
 service 
 . 
 google_ads 
  
 seed_customer_ids 
  
 = 
  
 [] 
  
 if 
  
 manager_customer_id 
  
 seed_customer_ids 
 << 
 manager_customer_id 
  
 else 
  
 puts 
  
 'No manager customer ID is specified. The example will print the ' 
  
 + 
  
 'hierarchies of all accessible customer IDs:' 
  
 customer_resource_names 
  
 = 
  
 client 
 . 
 service 
 . 
 customer 
 . 
  
 list_accessible_customers 
 () 
 . 
 resource_names 
  
 customer_resource_names 
 . 
 each 
  
 do 
  
 | 
 res 
 | 
  
 seed_customer_ids 
 << 
 res 
 . 
 split 
 ( 
 '/' 
 ) 
 [ 
 1 
 ] 
  
 end 
  
 end 
  
 search_query 
  
 = 
  
<< ~ 
 QUERY 
  
 SELECT 
  
 customer_client 
 . 
 client_customer 
 , 
  
 customer_client 
 . 
 level 
 , 
  
 customer_client 
 . 
 manager 
 , 
  
 customer_client 
 . 
 descriptive_name 
 , 
  
 customer_client 
 . 
 currency_code 
 , 
  
 customer_client 
 . 
 time_zone 
 , 
  
 customer_client 
 . 
 id 
  
 FROM 
  
 customer_client 
  
 WHERE 
  
 customer_client 
 . 
 level 
  
< = 
  
 1 
  
 QUERY 
  
 seed_customer_ids 
 . 
 each 
  
 do 
  
 | 
 seed_cid 
 | 
  
 # Performs a breadth-first search to build a dictionary that maps managers 
  
 # to their child accounts (cid_to_children). 
  
 unprocessed_customer_ids 
  
 = 
  
 Queue 
 . 
 new 
  
 unprocessed_customer_ids 
 << 
 seed_cid 
  
 cid_to_children 
  
 = 
  
 Hash 
 . 
 new 
  
 { 
  
 | 
 h 
 , 
  
 k 
 | 
  
 h 
 [ 
 k 
 ] 
  
 = 
  
 [] 
  
 } 
  
 root_customer_client 
  
 = 
  
 nil 
  
 while 
  
 unprocessed_customer_ids 
 . 
 size 
 > 
 0 
  
 cid 
  
 = 
  
 unprocessed_customer_ids 
 . 
 pop 
  
 response 
  
 = 
  
 google_ads_service 
 . 
 search 
 ( 
  
 customer_id 
 : 
  
 cid 
 , 
  
 query 
 : 
  
 search_query 
 , 
  
 ) 
  
 # Iterates over all rows in all pages to get all customer clients under 
  
 # the specified customer's hierarchy. 
  
 response 
 . 
 each 
  
 do 
  
 | 
 row 
 | 
  
 customer_client 
  
 = 
  
 row 
 . 
 customer_client 
  
 # The customer client that with level 0 is the specified customer 
  
 if 
  
 customer_client 
 . 
 level 
  
 == 
  
 0 
  
 if 
  
 root_customer_client 
  
 == 
  
 nil 
  
 root_customer_client 
  
 = 
  
 customer_client 
  
 end 
  
 next 
  
 end 
  
 # For all level-1 (direct child) accounts that are a manager account, 
  
 # the above query will be run against them to create a dictionary of 
  
 # managers mapped to their child accounts for printing the hierarchy 
  
 # afterwards. 
  
 cid_to_children 
 [ 
 cid 
 . 
 to_s 
 ] 
 << 
 customer_client 
  
 unless 
  
 customer_client 
 . 
 manager 
 . 
 nil? 
  
 if 
  
 ! 
 cid_to_children 
 . 
 key? 
 ( 
 customer_client 
 . 
 id 
 . 
 to_s 
 ) 
  
&&  
 customer_client 
 . 
 level 
  
 == 
  
 1 
  
 unprocessed_customer_ids 
 << 
 customer_client 
 . 
 id 
 . 
 to_s 
  
 end 
  
 end 
  
 end 
  
 end 
  
 if 
  
 root_customer_client 
  
 puts 
  
 "The hierarychy of customer ID 
 #{ 
 root_customer_client 
 . 
 id 
 } 
 " 
  
 + 
  
 "is printed below:" 
  
 print_account_hierarchy 
 ( 
 root_customer_client 
 , 
  
 cid_to_children 
 , 
  
 0 
 ) 
  
 else 
  
 puts 
  
 "Customer ID 
 #{ 
 manager_customer_id 
 } 
 is likely a test account, " 
  
 \ 
  
 "so its customer client information cannot be retrieved." 
  
 end 
  
 end 
 end 
 def 
  
 print_account_hierarchy 
 ( 
 customer_client 
 , 
  
 cid_to_children 
 , 
  
 depth 
 ) 
  
 if 
  
 depth 
  
 == 
  
 0 
  
 puts 
  
 'Customer ID (Descriptive Name, Currency Code, Time Zone)' 
  
 end 
  
 customer_id 
  
 = 
  
 customer_client 
 . 
 id 
  
 puts 
  
 '-' 
  
 * 
  
 ( 
 depth 
  
 * 
  
 2 
 ) 
  
 + 
  
 " 
 #{ 
 customer_id 
 } 
  
 #{ 
 customer_client 
 . 
 descriptive_name 
 } 
 " 
  
 + 
  
 " 
 #{ 
 customer_client 
 . 
 currency_code 
 } 
  
 #{ 
 customer_client 
 . 
 time_zone 
 } 
 " 
  
 # Recursively call this function for all child accounts of customer_client 
  
 if 
  
 cid_to_children 
 . 
 key? 
 ( 
 customer_id 
 . 
 to_s 
 ) 
  
 cid_to_children 
 [ 
 customer_id 
 . 
 to_s 
 ]. 
 each 
  
 do 
  
 | 
 child 
 | 
  
 print_account_hierarchy 
 ( 
 child 
 , 
  
 cid_to_children 
 , 
  
 depth 
  
 + 
  
 1 
 ) 
  
 end 
  
 end 
 end 
 if 
  
 __FILE__ 
  
 == 
  
 $PROGRAM_NAME 
  
 options 
  
 = 
  
 {} 
  
 # The following parameter(s) should be provided to run the example. You can 
  
 # either specify these by changing the INSERT_XXX_ID_HERE values below, or on 
  
 # the command line. 
  
 # 
  
 # Parameters passed on the command line will override any parameters set in 
  
 # code. 
  
 # 
  
 # Running the example with -h will print the command line usage. 
  
 options 
 [ 
 :customer_id 
 ] 
  
 = 
  
 nil 
  
 OptionParser 
 . 
 new 
  
 do 
  
 | 
 opts 
 | 
  
 opts 
 . 
 banner 
  
 = 
  
 sprintf 
 ( 
 'Usage: ruby %s [options]' 
 , 
  
 File 
 . 
 basename 
 ( 
 __FILE__ 
 )) 
  
 opts 
 . 
 separator 
  
 '' 
  
 opts 
 . 
 separator 
  
 'Options:' 
  
 opts 
 . 
 on 
 ( 
 '-M' 
 , 
  
 '--manager-customer-id MANAGER-CUSTOMER-ID' 
 , 
  
 String 
 , 
  
 'Manager Customer ID (optional)' 
 ) 
  
 do 
  
 | 
 v 
 | 
  
 options 
 [ 
 :manager_customer_id 
 ] 
  
 = 
  
 v 
 . 
 tr 
 ( 
 "-" 
 , 
  
 "" 
 ) 
  
 end 
  
 opts 
 . 
 on 
 ( 
 '-L' 
 , 
  
 '--login-customer-id LOGIN-CUSTOMER-ID' 
 , 
  
 String 
 , 
  
 'Login Customer ID (optional)' 
 ) 
  
 do 
  
 | 
 v 
 | 
  
 options 
 [ 
 :login_customer_id 
 ] 
  
 = 
  
 v 
 . 
 tr 
 ( 
 "-" 
 , 
  
 "" 
 ) 
  
 end 
  
 opts 
 . 
 separator 
  
 '' 
  
 opts 
 . 
 separator 
  
 'Help:' 
  
 opts 
 . 
 on_tail 
 ( 
 '-h' 
 , 
  
 '--help' 
 , 
  
 'Show this message' 
 ) 
  
 do 
  
 puts 
  
 opts 
  
 exit 
  
 end 
  
 end 
 . 
 parse! 
  
 begin 
  
 get_account_hierarchy 
 ( 
  
 options 
 [ 
 :manager_customer_id 
 ] 
 , 
  
 options 
 [ 
 :login_customer_id 
 ] 
 , 
  
 ) 
  
 rescue 
  
 Google 
 :: 
 Ads 
 :: 
 GoogleAds 
 :: 
 Errors 
 :: 
 GoogleAdsError 
  
 = 
>  
 e 
  
 e 
 . 
 failure 
 . 
 errors 
 . 
 each 
  
 do 
  
 | 
 error 
 | 
  
 STDERR 
 . 
 printf 
 ( 
 "Error with message: %s 
 \n 
 " 
 , 
  
 error 
 . 
 message 
 ) 
  
 if 
  
 error 
 . 
 location 
  
 error 
 . 
 location 
 . 
 field_path_elements 
 . 
 each 
  
 do 
  
 | 
 field_path_element 
 | 
  
 STDERR 
 . 
 printf 
 ( 
 " 
 \t 
 On field: %s 
 \n 
 " 
 , 
  
 field_path_element 
 . 
 field_name 
 ) 
  
 end 
  
 end 
  
 error 
 . 
 error_code 
 . 
 to_h 
 . 
 each 
  
 do 
  
 | 
 k 
 , 
  
 v 
 | 
  
 next 
  
 if 
  
 v 
  
 == 
  
 :UNSPECIFIED 
  
 STDERR 
 . 
 printf 
 ( 
 " 
 \t 
 Type: %s 
 \n\t 
 Code: %s 
 \n 
 " 
 , 
  
 k 
 , 
  
 v 
 ) 
  
 end 
  
 end 
  
 raise 
  
 end 
 end 
  
  

Perl

 #!/usr/bin/perl -w 
 # 
 # Copyright 2020, Google LLC 
 # 
 # Licensed under the Apache License, Version 2.0 (the "License"); 
 # you may not use this file except in compliance with the License. 
 # You may obtain a copy of the License at 
 # 
 #     http://www.apache.org/licenses/LICENSE-2.0 
 # 
 # Unless required by applicable law or agreed to in writing, software 
 # distributed under the License is distributed on an "AS IS" BASIS, 
 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
 # See the License for the specific language governing permissions and 
 # limitations under the License. 
 # 
 # Gets the account hierarchy of the specified manager customer ID and login customer 
 # ID. If you don't specify them, the example will instead print the hierarchies 
 # of all accessible customer accounts for your authenticated Google account. 
 # 
 # Note that if the list of accessible customers for your authenticated Google 
 # account includes accounts within the same hierarchy, this example will retrieve 
 # and print the overlapping portions of the hierarchy for each accessible customer. 
 use 
  
 strict 
 ; 
 use 
  
 warnings 
 ; 
 use 
  
 utf8 
 ; 
 use 
  
 FindBin 
  
 qw($Bin) 
 ; 
 use 
  
 lib 
  
 "$Bin/../../lib" 
 ; 
 use 
  
 Google::Ads::GoogleAds::Client 
 ; 
 use 
  
 Google::Ads::GoogleAds::Utils::GoogleAdsHelper 
 ; 
 use 
  
 Google::Ads::GoogleAds::Utils::SearchStreamHandler 
 ; 
 use 
  
 Google::Ads::GoogleAds::V21::Services::GoogleAdsService::SearchGoogleAdsStreamRequest 
 ; 
 use 
  
 Getopt::Long 
  
 qw(:config auto_help) 
 ; 
 use 
  
 Pod::Usage 
 ; 
 use 
  
 Cwd 
  
 qw(abs_path) 
 ; 
 # The following parameter(s) should be provided to run the example. You can 
 # either specify these by changing the INSERT_XXX_ID_HERE values below, or on 
 # the command line. 
 # 
 # Parameters passed on the command line will override any parameters set in 
 # code. 
 # 
 # Running the example with -h will print the command line usage. 
 # 
 # Optional: You may pass the manager customer ID on the command line or specify 
 # it here. If neither are set, a null value will be passed to run the example, 
 # and the example will print the hierarchies of all accessible customer IDs. 
 my 
  
 $manager_customer_id 
  
 = 
  
 undef 
 ; 
 # Optional: You may pass the login customer ID on the command line or specify it 
 # here if and only if the manager customer ID is set. If the login customer ID 
 # is set neither on the command line nor below, a null value will be passed to 
 # run the example, and the example will use each accessible customer ID as the 
 # login customer ID. 
 my 
  
 $login_customer_id 
  
 = 
  
 undef 
 ; 
 # Stores the mapping from the root customer IDs (the ones that will be used as a 
 # start point for printing each hierarchy) to their `CustomerClient` objects. 
 my 
  
 $root_customer_clients 
  
 = 
  
 {}; 
 sub 
  
 get_account_hierarchy 
  
 { 
  
 my 
  
 ( 
 $api_client 
 , 
  
 $manager_customer_id 
 , 
  
 $login_customer_id 
 ) 
  
 = 
  
 @_ 
 ; 
  
 my 
  
 $root_customer_ids 
  
 = 
  
 [] 
 ; 
  
 if 
  
 ( 
 not 
  
 $manager_customer_id 
 ) 
  
 { 
  
 # Get the account hierarchies for all accessible customers. 
  
 $root_customer_ids 
  
 = 
  
 get_accessible_customers 
 ( 
 $api_client 
 ); 
  
 } 
  
 else 
  
 { 
  
 # Only get the hierarchy for the provided manager customer ID if provided. 
  
 push 
  
 @$root_customer_ids 
 , 
  
 $manager_customer_id 
 ; 
  
 } 
  
 my 
  
 $all_hierarchies 
  
 = 
  
 {}; 
  
 my 
  
 $accounts_with_no_info 
  
 = 
  
 [] 
 ; 
  
 # Construct a map of account hierarchies. 
  
 foreach 
  
 my 
  
 $root_customer_id 
  
 ( 
 @$root_customer_ids 
 ) 
  
 { 
  
 my 
  
 $customer_client_to_hierarchy 
  
 = 
  
 create_customer_client_to_hierarchy 
 ( 
 $login_customer_id 
 , 
  
 $root_customer_id 
 ); 
  
 if 
  
 ( 
 not 
  
 $customer_client_to_hierarchy 
 ) 
  
 { 
  
 push 
  
 @$accounts_with_no_info 
 , 
  
 $root_customer_id 
 ; 
  
 } 
  
 else 
  
 { 
  
 $all_hierarchies 
  
 = 
  
 { 
 %$all_hierarchies 
 , 
  
 %$customer_client_to_hierarchy 
 }; 
  
 } 
  
 } 
  
 # Print the IDs of any accounts that did not produce hierarchy information. 
  
 if 
  
 ( 
 scalar 
  
 @$accounts_with_no_info 
 > 
 0 
 ) 
  
 { 
  
 print 
  
 "Unable to retrieve information for the following accounts " 
  
 . 
  
 "which are likely either test accounts or accounts with setup issues. " 
  
 . 
  
 "Please check the logs for details:\n" 
 ; 
  
 foreach 
  
 my 
  
 $account_id 
  
 ( 
 @$accounts_with_no_info 
 ) 
  
 { 
  
 print 
  
 "$account_id\n" 
 ; 
  
 } 
  
 print 
  
 "\n" 
 ; 
  
 } 
  
 # Print the hierarchy information for all accounts for which there is hierarchy 
  
 # information available. 
  
 foreach 
  
 my 
  
 $root_customer_id 
  
 ( 
 keys 
  
 %$all_hierarchies 
 ) 
  
 { 
  
 printf 
  
 "The hierarchy of customer ID %d is printed below:\n" 
 , 
  
 $root_customer_id 
 ; 
  
 print_account_hierarchy 
 ( 
 $root_customer_clients 
 - 
> { 
 $root_customer_id 
 }, 
  
 $all_hierarchies 
 - 
> { 
 $root_customer_id 
 }, 
  
 0 
 ); 
  
 print 
  
 "\n" 
 ; 
  
 } 
  
 return 
  
 1 
 ; 
 } 
 # Retrieves a list of accessible customers with the provided set up credentials. 
 sub 
  
 get_accessible_customers 
  
 { 
  
 my 
  
 $api_client 
  
 = 
  
 shift 
 ; 
  
 my 
  
 $accessible_customer_ids 
  
 = 
  
 [] 
 ; 
  
 # Issue a request for listing all customers accessible by this authenticated 
  
 # Google account. 
  
 my 
  
 $list_accessible_customers_response 
  
 = 
  
 $api_client 
 - 
> CustomerService 
 () 
 - 
> list_accessible_customers 
 (); 
  
 print 
  
 "No manager customer ID is specified. The example will print the " 
  
 . 
  
 "hierarchies of all accessible customer IDs:\n" 
 ; 
  
 foreach 
  
 my 
  
 $customer_resource_name 
  
 ( 
  
 @ 
 { 
 $list_accessible_customers_response 
 - 
> { 
 resourceNames 
 }}) 
  
 { 
  
 my 
  
 $customer_id 
  
 = 
  
 $1 
  
 if 
  
 $customer_resource_name 
  
 =~ 
 /(\d+)$/ 
 ; 
  
 print 
  
 "$customer_id\n" 
 ; 
  
 push 
  
 @$accessible_customer_ids 
 , 
  
 $customer_id 
 ; 
  
 } 
  
 return 
  
 $accessible_customer_ids 
 ; 
 } 
 # Creates a map between a customer client and each of its managers' mappings. 
 sub 
  
 create_customer_client_to_hierarchy 
 () 
  
 { 
  
 my 
  
 ( 
 $login_customer_id 
 , 
  
 $root_customer_id 
 ) 
  
 = 
  
 @_ 
 ; 
  
 # Create a GoogleAdsClient with the specified login customer ID. Seec 
  
 # https://developers.google.com/google-ads/api/docs/concepts/call-structure#cid 
  
 # for more information. 
  
 my 
  
 $api_client 
  
 = 
  
 Google::Ads::GoogleAds:: 
 Client 
 - 
> new 
 ({ 
  
 login_customer_id 
  
 = 
>  
 $login_customer_id 
  
 || 
  
 $root_customer_id 
  
 }); 
  
 # Get the GoogleAdsService. 
  
 my 
  
 $google_ads_service 
  
 = 
  
 $api_client 
 - 
> GoogleAdsService 
 (); 
  
 # Create a query that retrieves all child accounts of the manager specified in 
  
 # search calls below. 
  
 my 
  
 $search_query 
  
 = 
  
 "SELECT customer_client.client_customer, customer_client.level, " 
  
 . 
  
 "customer_client.manager, customer_client.descriptive_name, " 
  
 . 
  
 "customer_client.currency_code, customer_client.time_zone, " 
  
 . 
  
 "customer_client.id " 
  
 . 
  
 "FROM customer_client WHERE customer_client.level <= 1" 
 ; 
  
 my 
  
 $root_customer_client 
  
 = 
  
 undef 
 ; 
  
 # Add the root customer ID to the list of IDs to be processed. 
  
 my 
  
 $manager_customer_ids_to_search 
  
 = 
  
 [ 
 $root_customer_id 
 ]; 
  
 # Perform a breadth-first search algorithm to build a mapping of managers to 
  
 # their child accounts. 
  
 my 
  
 $customer_ids_to_child_accounts 
  
 = 
  
 {}; 
  
 while 
  
 ( 
 scalar 
  
 @$manager_customer_ids_to_search 
 > 
 0 
 ) 
  
 { 
  
 my 
  
 $customer_id_to_search 
  
 = 
  
 shift 
  
 @$manager_customer_ids_to_search 
 ; 
  
 $customer_ids_to_child_accounts 
 - 
> { 
 $customer_id_to_search 
 } 
  
 ||= 
  
 [] 
 ; 
  
 my 
  
 $search_stream_handler 
  
 = 
  
 Google::Ads::GoogleAds::Utils:: 
 SearchStreamHandler 
 - 
> new 
 ({ 
  
 service 
  
 = 
>  
 $google_ads_service 
 , 
  
 request 
  
 = 
>  
 Google::Ads::GoogleAds::V21::Services::GoogleAdsService:: 
 SearchGoogleAdsStreamRequest 
  
 - 
> new 
 ({ 
  
 customerId 
  
 = 
>  
 $customer_id_to_search 
 , 
  
 query 
  
 = 
>  
 $search_query 
 , 
  
 })}); 
  
 # Iterate over all elements to get all customer clients under the specified 
  
 # customer's hierarchy. 
  
 $search_stream_handler 
 - 
> process_contents 
 ( 
  
 sub 
  
 { 
  
 my 
  
 $google_ads_row 
  
 = 
  
 shift 
 ; 
  
 my 
  
 $customer_client 
  
 = 
  
 $google_ads_row 
 - 
> { 
 customerClient 
 }; 
  
 # Get the CustomerClient object for the root customer in the tree. 
  
 if 
  
 ( 
 $customer_client 
 - 
> { 
 id 
 } 
  
 == 
  
 $root_customer_id 
 ) 
  
 { 
  
 $root_customer_client 
  
 = 
  
 $customer_client 
 ; 
  
 $root_customer_clients 
 - 
> { 
 $root_customer_id 
 } 
  
 = 
  
 $root_customer_client 
 ; 
  
 } 
  
 # The steps below map parent and children accounts. Return here so that 
  
 # manager accounts exclude themselves from the list of their children 
  
 # accounts. 
  
 if 
  
 ( 
 $customer_client 
 - 
> { 
 id 
 } 
  
 == 
  
 $customer_id_to_search 
 ) 
  
 { 
  
 return 
 ; 
  
 } 
  
 # For all level-1 (direct child) accounts that are manager accounts, the 
  
 # above query will be run against them to create a map of managers to their 
  
 # child accounts for printing the hierarchy afterwards. 
  
 push 
  
 @ 
 { 
 $customer_ids_to_child_accounts 
 - 
> { 
 $customer_id_to_search 
 }}, 
  
 $customer_client 
 ; 
  
 # Check if the child account is a manager itself so that it can later be 
  
 # processed and added to the map if it hasn't been already. 
  
 if 
  
 ( 
 $customer_client 
 - 
> { 
 manager 
 }) 
  
 { 
  
 # A customer can be managed by multiple managers, so to prevent visiting 
  
 # the same customer multiple times, we need to check if it's already 
  
 # in the map. 
  
 my 
  
 $already_visited 
  
 = 
  
 exists 
  
 $customer_ids_to_child_accounts 
 - 
> { 
 $customer_client 
 - 
> { 
 id 
 }}; 
  
 if 
  
 ( 
 not 
  
 $already_visited 
 && 
 $customer_client 
 - 
> { 
 level 
 } 
  
 == 
  
 1 
 ) 
  
 { 
  
 push 
  
 @$manager_customer_ids_to_search 
 , 
  
 $customer_client 
 - 
> { 
 id 
 }; 
  
 } 
  
 } 
  
 }); 
  
 } 
  
 return 
  
 $root_customer_client 
  
 ? 
  
 { 
 $root_customer_client 
 - 
> { 
 id 
 } 
  
 = 
>  
 $customer_ids_to_child_accounts 
 } 
  
 : 
  
 undef 
 ; 
 } 
 # Prints the specified account's hierarchy using recursion. 
 sub 
  
 print_account_hierarchy 
  
 { 
  
 my 
  
 ( 
 $customer_client 
 , 
  
 $customer_ids_to_child_accounts 
 , 
  
 $depth 
 ) 
  
 = 
  
 @_ 
 ; 
  
 if 
  
 ( 
 $depth 
  
 == 
  
 0 
 ) 
  
 { 
  
 print 
  
 "Customer ID (Descriptive Name, Currency Code, Time Zone)\n" 
 ; 
  
 } 
  
 my 
  
 $customer_id 
  
 = 
  
 $customer_client 
 - 
> { 
 id 
 }; 
  
 print 
  
 "--" 
  
 x 
  
 $depth 
 ; 
  
 printf 
  
 " %d ('%s', '%s', '%s')\n" 
 , 
  
 $customer_id 
 , 
  
 $customer_client 
 - 
> { 
 descriptiveName 
 } 
  
 || 
  
 "" 
 , 
  
 $customer_client 
 - 
> { 
 currencyCode 
 }, 
  
 $customer_client 
 - 
> { 
 timeZone 
 }; 
  
 # Recursively call this function for all child accounts of $customer_client. 
  
 if 
  
 ( 
 exists 
  
 $customer_ids_to_child_accounts 
 - 
> { 
 $customer_id 
 }) 
  
 { 
  
 foreach 
  
 my 
  
 $child_account 
  
 ( 
 @ 
 { 
 $customer_ids_to_child_accounts 
 - 
> { 
 $customer_id 
 }}) 
  
 { 
  
 print_account_hierarchy 
 ( 
 $child_account 
 , 
  
 $customer_ids_to_child_accounts 
 , 
  
 $depth 
  
 + 
  
 1 
 ); 
  
 } 
  
 } 
 } 
 # Don't run the example if the file is being included. 
 if 
  
 ( 
 abs_path 
 ( 
 $0 
 ) 
  
 ne 
  
 abs_path 
 ( 
 __FILE__ 
 )) 
  
 { 
  
 return 
  
 1 
 ; 
 } 
 # Get Google Ads Client, credentials will be read from ~/googleads.properties. 
 my 
  
 $api_client 
  
 = 
  
 Google::Ads::GoogleAds:: 
 Client 
 - 
> new 
 (); 
 # By default examples are set to die on any server returned fault. 
 $api_client 
 - 
> set_die_on_faults 
 ( 
 1 
 ); 
 # Parameters passed on the command line will override any parameters set in code. 
 GetOptions 
 ( 
  
 "manager_customer_id=s" 
  
 = 
>  
 \ 
 $manager_customer_id 
 , 
  
 "login_customer_id=s" 
  
 = 
>  
 \ 
 $login_customer_id 
 ); 
 if 
  
 ( 
 $manager_customer_id 
  
 xor 
  
 $login_customer_id 
 ) 
  
 { 
  
 die 
  
 "Both the manager customer ID and login customer ID must be " 
  
 . 
  
 "provided together, or they must both be null.\n" 
 ; 
 } 
 # Call the example. 
 get_account_hierarchy 
 ( 
  
 $api_client 
 , 
  
 $manager_customer_id 
  
 ? 
  
 $manager_customer_id 
  
 =~ 
  
 s/-//g 
 r 
  
 : 
  
 undef 
 , 
  
 $login_customer_id 
  
 ? 
  
 $login_customer_id 
  
 =~ 
  
 s/-//g 
 r 
  
 : 
  
 undef 
 ); 
 =pod 
 =head1 NAME 
 get_account_hierarchy 
 =head1 DESCRIPTION 
 Gets the account hierarchy of the specified manager customer ID and login customer 
 ID. If you don't specify them, the example will instead print the hierarchies 
 of all accessible customer accounts for your authenticated Google account. 
 Note that if the list of accessible customers for your authenticated Google 
 account includes accounts within the same hierarchy, this example will retrieve 
 and print the overlapping portions of the hierarchy for each accessible customer. 
 =head1 SYNOPSIS 
 get_account_hierarchy.pl [options] 
 -help                       Show the help message. 
 -manager_customer_id        [optional] The Google Ads manager customer ID. 
 -login_customer_id          [optional] The login customer ID. 
 =cut 
  
  
Create a Mobile Website
View Site in Mobile | Classic
Share by: