customerId = getenv('GOOGLE_ADS_CUSTOMER_ID'); // // // OAuth2 Token Authentication // $oAuth2Credential = (new OAuth2TokenBuilder())->fromFile()->build(); // // // Google Ads Client initialization // $this->googleAdsClient = (new GoogleAdsClientBuilder()) // ->fromFile() // ->withOAuth2Credential($oAuth2Credential) // ->build(); } /** * Runs the example. * * @param $options * This example assumes that the same credentials will work for both customers, * but that may not be the case. If you need to use different credentials * for each customer, then you may either update the client configuration or * instantiate the clients accordingly, one for each set of credentials. Always make * sure to update the configuration before fetching any services you need to use. * // * @return mixed * @throws ApiException */ public function runLinkManagerToClient($options) { // Extends an invitation to the client while authenticating as the manager. $managerCustomerId = $options['manager_customer_id']; $clientCustomerId = $options['client_customer_id']; // Extends an invitation to the client while authenticating as the manager. $customerClientLinkResourceName = self::createInvitation( $managerCustomerId, $clientCustomerId ); // Retrieves the manager link information. $managerLinkResourceName = self::getManagerLinkResourceName( $managerCustomerId, $clientCustomerId, $customerClientLinkResourceName ); // Accepts the manager's invitation while authenticating as the client. return self::acceptInvitation($clientCustomerId, $managerLinkResourceName); } /** * Extends an invitation from a manager customer to a client customer. * * @param int $managerCustomerId the manager customer ID * @param int $clientCustomerId the customer ID * @return string the resource name of the customer client link created for the invitation */ public function createInvitation( int $managerCustomerId, int $clientCustomerId ) { // Creates a client with the manager customer ID as login customer ID. $googleAdsClient = $this->createGoogleAdsClient($managerCustomerId); // Creates a customer client link. $customerClientLink = new CustomerClientLink([ // Sets the client customer to invite. 'client_customer' => ResourceNames::forCustomer($clientCustomerId), 'status' => ManagerLinkStatus::PENDING ]); // Creates a customer client link operation for creating the one above. $customerClientLinkOperation = new CustomerClientLinkOperation(); $customerClientLinkOperation->setCreate($customerClientLink); // Issues a mutate request to create the customer client link. $customerClientLinkServiceClient = $googleAdsClient->getCustomerClientLinkServiceClient(); $response = $customerClientLinkServiceClient->mutateCustomerClientLink( MutateCustomerClientLinkRequest::build( $managerCustomerId, $customerClientLinkOperation ) ); // Prints the result. $customerClientLinkResourceName = $response->getResult()->getResourceName(); printf( "An invitation has been extended from the manager customer %d" . " to the client customer %d with the customer client link resource name '%s'.%s", $managerCustomerId, $clientCustomerId, $customerClientLinkResourceName, PHP_EOL ); // Returns the resource name of the created customer client link. return $customerClientLinkResourceName; } /** * Retrieves the manager link resource name of a customer client link given its resource name. * * @param int $managerCustomerId the manager customer ID * @param int $clientCustomerId the customer ID * @param string $customerClientLinkResourceName the customer client link resource name * @return string the manager link resource name */ public function getManagerLinkResourceName( int $managerCustomerId, int $clientCustomerId, string $customerClientLinkResourceName ) { // Creates a client with the manager customer ID as login customer ID. $googleAdsClient = $this->createGoogleAdsClient($managerCustomerId); // Creates the query. $query = "SELECT customer_client_link.manager_link_id FROM customer_client_link" . " WHERE customer_client_link.resource_name = '$customerClientLinkResourceName'"; // Issues a search request. $googleAdsServiceClient = $googleAdsClient->getGoogleAdsServiceClient(); $response = $googleAdsServiceClient->search( SearchGoogleAdsRequest::build($managerCustomerId, $query) ); // Gets the ID and resource name associated to the manager link found. $managerLinkId = $response->getIterator()->current() ->getCustomerClientLink() ->getManagerLinkId(); $managerLinkResourceName = ResourceNames::forCustomerManagerLink( $clientCustomerId, $managerCustomerId, $managerLinkId ); // Prints the result. printf( "Retrieved the manager link of the customer client link:" . " its ID is %d and its resource name is '%s'.%s", $managerLinkId, $managerLinkResourceName, PHP_EOL ); // Returns the resource name of the manager link found. return $managerLinkResourceName; } /** * Accepts an invitation. * * @param int $clientCustomerId the customer ID * @param string $managerLinkResourceName the resource name of the manager link to accept */ public function acceptInvitation( int $clientCustomerId, string $managerLinkResourceName ) { // Creates a client with the client customer ID as login customer ID. $googleAdsClient = $this->createGoogleAdsClient($clientCustomerId); // Creates the customer manager link with the updated status. $customerManagerLink = new CustomerManagerLink(); $customerManagerLink->setResourceName($managerLinkResourceName); $customerManagerLink->setStatus(ManagerLinkStatus::ACTIVE); // Creates a customer manager link operation for updating the one above. $customerManagerLinkOperation = new CustomerManagerLinkOperation(); $customerManagerLinkOperation->setUpdate($customerManagerLink); $customerManagerLinkOperation->setUpdateMask( FieldMasks::allSetFieldsOf($customerManagerLink) ); // Issues a mutate request to update the customer manager link. $customerManagerLinkServiceClient = $googleAdsClient->getCustomerManagerLinkServiceClient(); $response = $customerManagerLinkServiceClient->mutateCustomerManagerLink( MutateCustomerManagerLinkRequest::build( $clientCustomerId, [$customerManagerLinkOperation] ) ); // Prints the result. printf( "The client %d accepted the invitation with the resource name '%s'.%s", $clientCustomerId, $response->getResults()[0]->getResourceName(), PHP_EOL ); return $response->getResults()[0]->getResourceName(); } // [END link_manager_to_client] /** * Creates a Google Ads client based on the default configuration file * and a given login customer id. * * @param int $thirdUserId thirdUser * @return GoogleAdsClient the created client */ // public function createGoogleAdsClient(int $thirdUserId) public function createGoogleAdsClient($refreshToken) { // 从数据库获取 access_token // $refreshToken = $this->getRefreshTokenFromDatabase($thirdUserId); if (!$refreshToken) { throw new \Exception("Access token not found for advertiserId: " . $refreshToken); } // OAuth2 Token Authentication $oAuth2Credential = (new OAuth2TokenBuilder()) ->fromFile() // 如果需要从文件获取其他配置,可以继续使用 fromFile() ->withRefreshToken($refreshToken) // 使用动态获取的 access_token ->build(); // Builds and returns the Google Ads client return (new GoogleAdsClientBuilder()) // Sets the properties based on the default properties file ->fromFile() // eUses the OAuth2 credentials crated above. ->withOAuth2Credential($oAuth2Credential) // Overrides the login customer ID with the given one. ->build(); } /** * Creates a Google Ads client based on the default configuration file * and a given login customer id. * * @param int $loginCustomerId the login customer ID * @return GoogleAdsClient the created client */ // public function createGoogleAdsClientWithloginCustomerId(int $thirdUserId,int $loginCustomerId) public function createGoogleAdsClientWithloginCustomerId($refreshToken, int $loginCustomerId) { // $advertiserId = getenv('GOOGLE_ADS_CUSTOMER_ID'); // 从数据库获取 access_token // $refreshToken = $this->getRefreshTokenFromDatabase($thirdUserId); if (!$refreshToken) { throw new \Exception("Access token not found for advertiserId: " . $refreshToken); } // OAuth2 Token Authentication $oAuth2Credential = (new OAuth2TokenBuilder()) ->fromFile() // 如果需要从文件获取其他配置,可以继续使用 fromFile() ->withRefreshToken($refreshToken) // 使用动态获取的 access_token ->build(); // Builds and returns the Google Ads client return ( new GoogleAdsClientBuilder()) // Sets the properties based on the default properties file ->fromFile() // eUses the OAuth2 credentials crated above. ->withOAuth2Credential($oAuth2Credential) // Overrides the login customer ID with the given one. ->withLoginCustomerId($loginCustomerId) ->build(); } /** * Runs the example. * * @param GoogleAdsClient $googleAdsClient the Google Ads API client */ // [START list_accessible_customers] public function runListAccessibleCustomers($option) { // $loginCustomerId = $option['customer_id']; $refreshToken = $option['refresh_token']; // Creates a client with the manager customer ID as login customer ID. $googleAdsClient = $this->createGoogleAdsClient($refreshToken); $customerServiceClient = $googleAdsClient->getCustomerServiceClient(); // Issues a request for listing all accessible customers. $accessibleCustomers = $customerServiceClient->listAccessibleCustomers(new ListAccessibleCustomersRequest()); $accessibleCustomerIds = []; foreach ($accessibleCustomers->getResourceNames() as $customerResourceName) { $customer = CustomerServiceClient::parseName($customerResourceName)['customer_id']; print $customer . PHP_EOL; $accessibleCustomerIds[] = intval($customer); } return $accessibleCustomerIds; // print 'Total results: ' . count($accessibleCustomers->getResourceNames()) . PHP_EOL; // $resourceNameArray = []; // // 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); // $resourceNameArray[] = $resourceName; // } // return $resourceNameArray; } // [END list_accessible_customers] /** * Runs the example. * * @param GoogleAdsClient $googleAdsClient the Google Ads API client * @param int $customerId the customer ID * @param string $emailAddress the email address of the user whose access role should be updated * @param string $accessRole the updated access role */ public function runGetAccountAccess( $option) { $managerCustomerId = isset($option['manager_customer_id']) ? (int)$option['manager_customer_id'] : null; $loginCustomerId = isset($option['login_customer_id']) ? (int)$option['login_customer_id'] : null; $refreshToken = isset($option['refresh_token']) ? $option['refresh_token'] : null; // $thirdUserId = (int)$option['third_user_id']; // Creates a client with the manager customer ID as login customer ID. $googleAdsClient = $this->createGoogleAdsClientWithloginCustomerId($refreshToken,$loginCustomerId); $customerId = 8452924576; $userId = $this->getUserAccess($googleAdsClient, $customerId,'s5O0z@example.com'); // if (!is_null($userId)) { // $this->modifyUserAccess($googleAdsClient, $customerId, $userId, $accessRole); // } return $userId; } /** * Gets the customer user access given an email address. * * @param GoogleAdsClient $googleAdsClient the Google Ads API client * @param int $customerId the customer ID * @param string $emailAddress the email address of the user whose access role should be updated * @return int|null the user ID if a customer is found, or null if no matching customers were * found */ public function getUserAccess( GoogleAdsClient $googleAdsClient, int $customerId, string $emailAddress ) { $googleAdsServiceClient = $googleAdsClient->getGoogleAdsServiceClient(); // Creates a query that retrieves all customer user accesses. // Use the LIKE query for filtering to ignore the text case for email address when // searching for a match. // $query = "SELECT customer_user_access.user_id, " // . "customer_user_access.email_address, customer_user_access.access_role," // . "customer_user_access.access_creation_date_time FROM customer_user_access " // . "WHERE customer_user_access.email_address LIKE '$emailAddress'"; $query = "SELECT customer_user_access.user_id, " . "customer_user_access.email_address, customer_user_access.access_role," . "customer_user_access.access_creation_date_time FROM customer_user_access " . "WHERE customer_user_access.user_id = $customerId"; // Issues a search request by to retrieve the customer user accesses. $response = $googleAdsServiceClient->search(SearchGoogleAdsRequest::build($customerId, $query)); if (iterator_count($response) > 0) { /** @var CustomerUserAccess $customerUserAccess */ $customerUserAccess = $response->getIterator()->current()->getCustomerUserAccess(); printf( "Customer user access with User ID = %d, Email Address = " . "'%s', Access Role = '%s' and Creation Time = %s was found in " . "Customer ID: %d.%s", $customerUserAccess->getUserId(), $customerUserAccess->getEmailAddress(), AccessRole::name($customerUserAccess->getAccessRole()), $customerUserAccess->getAccessCreationDateTime(), $customerId, PHP_EOL ); return $customerUserAccess->getUserId(); } else { print 'No customer user access with requested email was found.' . PHP_EOL; return null; } } /** * Modifies the user access role to a specified value. * * @param GoogleAdsClient $googleAdsClient the Google Ads API client * @param int $customerId the customer ID * @param int $userId ID of the user whose access role is modified * @param string $accessRole the updated access role */ public function modifyUserAccess( GoogleAdsClient $googleAdsClient, int $customerId, int $userId, string $accessRole ) { // Creates the modified user access. $customerUserAccess = new CustomerUserAccess([ 'resource_name' => ResourceNames::forCustomerUserAccess($customerId, $userId), 'access_role' => AccessRole::value($accessRole) ]); // Constructs an operation that will update the customer user access with the specified // resource name, using the FieldMasks utility to derive the update mask. This mask tells // the Google Ads API which attributes of the customer user access you want to change. $customerUserAccessOperation = new CustomerUserAccessOperation(); $customerUserAccessOperation->setUpdate($customerUserAccess); $customerUserAccessOperation->setUpdateMask( FieldMasks::allSetFieldsOf($customerUserAccess) ); // Issues a mutate request to update the customer user access. $customerUserAccessServiceClient = $googleAdsClient->getCustomerUserAccessServiceClient(); $response = $customerUserAccessServiceClient->mutateCustomerUserAccess( MutateCustomerUserAccessRequest::build($customerId, $customerUserAccessOperation) ); // Prints the resource name of the updated customer user access. printf( "Successfully modified customer user access with resource name: '%s'%s", $response->getResult()->getResourceName(), PHP_EOL ); } /** * 层级账号信息 * */ public function runGetAccountHierarchy( $option ) { self::$rootCustomerClients = []; //初始化静态变量 $managerCustomerId = isset($option['manager_customer_id']) ? (int)$option['manager_customer_id'] : null; $loginCustomerId = isset($option['login_customer_id']) ? (int)$option['login_customer_id'] : null; $refreshToken = isset($option['refresh_token']) ? $option['refresh_token'] : null; // $thirdUserId = (int)$option['third_user_id']; // Creates a client with the manager customer ID as login customer ID. $googleAdsClient = $this->createGoogleAdsClient($refreshToken); // $customerServiceClient = $googleAdsClient->getCustomerServiceClient(); $rootCustomerIds = []; if (is_null($managerCustomerId)) { // We will get the account hierarchies for all accessible customers. $rootCustomerIds = $this->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 = $this->createCustomerClientToHierarchy($refreshToken, $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; } $allAccounts = []; // 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 // ); // 获取所有账户的数组(包括根账户及其子账户) $accounts = []; self::getAccountHierarchy( self::$rootCustomerClients[$rootCustomerId], $customerIdsToChildAccounts, 0, $accounts); $allAccounts[$rootCustomerId] = $accounts; // self::printAccountHierarchy( // self::$rootCustomerClients[$rootCustomerId], // $customerIdsToChildAccounts, // 0 // ); // print PHP_EOL; } // dump($allAccounts); return $allAccounts; } /** * 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 */ public function createCustomerClientToHierarchy( string $refreshToken, ?int $loginCustomerId, int $rootCustomerId ): ?array { // Creates a client with the manager customer ID as login customer ID. $googleAdsClient = $this->createGoogleAdsClientWithloginCustomerId($refreshToken, $loginCustomerId ?? $rootCustomerId); // 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.test_account, 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 */ public 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, Manager, Test Account)' . PHP_EOL; } $customerId = $customerClient->getId(); print str_repeat('-', $depth * 2); printf( " %d ('%s', '%s', '%s', '%s', '%s')%s", $customerId, $customerClient->getDescriptiveName(), $customerClient->getCurrencyCode(), $customerClient->getTimeZone(), $customerClient->getManager(), $customerClient->getTestAccount(), 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); } } } private static function getAccountHierarchy( CustomerClient $customerClient, array $customerIdsToChildAccounts, int $depth, array &$result = [] // 这里使用引用传递 ) { // Store the current customer ID and descriptive name in the result array $customerId = $customerClient->getId(); $result[] = [ 'customer_id' => $customerId, 'descriptive_name' => $customerClient->getDescriptiveName(), 'manager' => $customerClient->getManager(), 'test_account' => $customerClient->getTestAccount(), 'currency' => $customerClient->getCurrencyCode(), 'status' => $customerClient->getStatus(), 'level' => $customerClient->getLevel(), 'time_zone' => $customerClient->getTimeZone(), ]; // Recursively call this function for all child accounts of $customerClient. if (array_key_exists($customerId, $customerIdsToChildAccounts)) { foreach ($customerIdsToChildAccounts[$customerId] as $childAccount) { // Recursively add the child account information $result = self::getAccountHierarchy($childAccount, $customerIdsToChildAccounts, $depth + 1, $result); } } return $result; } }