i have a laravel project which uses the google ads api, and i am attempting to make a select from the `customer_client` table but getting unanticipated results.
of the four initial customers that i get in `runExample` by calling `getAccessibleCustomers`, one should be a manager account with several customers 'under' it. however, when i run this code, i only see the top level customers. the heirarchy is flat. my code is below and is a mostly copy-paste job from the example google code at: https://developers.google.com/google-ads/api/docs/account-management/get-account-hierarchy the main differences, i believe, is in my construction of the oauthToken and googleAdsClient. any assistance or insight is greatly appreciated! <?php namespace App\Libs; require_once(__DIR__."/../../vendor/autoload.php"); use DB; use Exception; use Carbon\Carbon; use Illuminate\Http\Request; use Illuminate\Support\Facades\Storage; use Illuminate\Support\Str; 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\V12\GoogleAdsClient; use Google\Ads\GoogleAds\Lib\V12\GoogleAdsClientBuilder; use Google\Ads\GoogleAds\Lib\V12\GoogleAdsException; use Google\Ads\GoogleAds\Lib\V12\GoogleAdsServerStreamDecorator; use Google\Ads\GoogleAds\V12\Errors\GoogleAdsError; use Google\Ads\GoogleAds\V12\Resources\CustomerClient; use Google\Ads\GoogleAds\V12\Services\CustomerServiceClient; use Google\Ads\GoogleAds\V12\Services\GoogleAdsRow; use Google\ApiCore\ApiException; class GoogleAds { /** * The results from the example code */ private static $rootCustomerClients = []; /** * Main */ public function getGoogleAdsCustomersTest(bool $resetCache = false) { /** * Hard codes of values of OAuth2TokenBuilder and GoogleAdsClientBuilder. * Normally stored in db. */ $clientId = "<client id>.apps.googleusercontent.com"; $clientSecret = "<client secret>"; $refreshToken = "<refresh token>"; $developerToken = "<developer token>"; /** * Create oauth with values, not fromFile() */ $oauthToken = (new \Google\Ads\GoogleAds\Lib\OAuth2TokenBuilder()) ->withClientId($clientId) ->withClientSecret($clientSecret) ->withRefreshToken($refreshToken) ->build(); /** * Create googleAdsClient with values, not fromFile() */ $googleAdsClient = (new \Google\Ads\GoogleAds\Lib\V12\GoogleAdsClientBuilder()) ->withOAuth2Credential($oauthToken) ->withDeveloperToken($this->developerToken) ->build(); self::runExample($googleAdsClient); } /** * runExample */ public static function runExample(GoogleAdsClient $googleAdsClient) { $rootCustomerIds = []; $rootCustomerIds = self::getAccessibleCustomers($googleAdsClient); $allHierarchies = []; $accountsWithNoInfo = []; // Constructs a map of account hierarchies. foreach ($rootCustomerIds as $rootCustomerId) { $customerClientToHierarchy = self::createCustomerClientToHierarchy($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; } } /** * getAccessibleCustomers */ 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(); 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); } } } /** * Create heirarchy */ private static function createCustomerClientToHierarchy(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. /** * Hard codes of values of OAuth2TokenBuilder and GoogleAdsClientBuilder. * Normally stored in db. */ $clientId = "<client id>.apps.googleusercontent.com"; $clientSecret = "<client secret>"; $refreshToken = "<refresh token>"; $developerToken = "<developer token>"; /** * Create oauth with values, not fromFile() */ $oauthToken = (new \Google\Ads\GoogleAds\Lib\OAuth2TokenBuilder()) ->withClientId($clientId) ->withClientSecret($clientSecret) ->withRefreshToken($refreshToken) ->build(); // Construct a Google Ads client configured from a properties file and the // OAuth2 credentials above. /** * Create googleAdsClient with values, not fromFile() */ $googleAdsClient = (new \Google\Ads\GoogleAds\Lib\V12\GoogleAdsClientBuilder()) ->withOAuth2Credential($oauthToken) ->withDeveloperToken($developerToken) ->withLoginCustomerId($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 by specifying page size. /** @var GoogleAdsServerStreamDecorator $stream */ try { $stream = $googleAdsServiceClient->searchStream( $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()); } } } } // try catch(\Exception $e) { } } // while return is_null($rootCustomerClient) ? null : [$rootCustomerClient->getId() => $customerIdsToChildAccounts]; } } -- -- =~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~ Also find us on our blog: https://googleadsdeveloper.blogspot.com/ =~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~ You received this message because you are subscribed to the Google Groups "AdWords API and Google Ads API Forum" group. To post to this group, send email to adwords-api@googlegroups.com To unsubscribe from this group, send email to adwords-api+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/adwords-api?hl=en --- You received this message because you are subscribed to the Google Groups "Google Ads API and AdWords API Forum" group. To unsubscribe from this group and stop receiving emails from it, send an email to adwords-api+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/adwords-api/b04bbd83-ff52-459c-9b7d-abff6c9cfb98n%40googlegroups.com.