Linking agency with his client using CustomerManagerLinkService with Basic Access Developer token

85 views
Skip to first unread message

Damian Szczepański

unread,
Jun 21, 2020, 11:29:15 AM6/21/20
to AdWords API and Google Ads API Forum
We are trying to use LinkManagerToClient.php to link agency to the agency client. Explanation of the 3 accounts:
ice_screenshot_20200621-170857.png












Agency and client already gave us permission for https://www.googleapis.com/auth/adwords scope with AuthenticateInWebApplication.php.
This article CustomerManagerLinkService doesn't have enough information about what we should specify in google_ads_php.ini. Inside google_ads_php.ini is our developerToken for Google Ads Manager Account 3191377543 and [OAUTH2] also for 3191377543 account. How we can use LinkManagerToClient.php to give agency access to his client with our Basic Access Developer token?

ice_screenshot_20200621-171315.png


Current error:

Fatal error: Uncaught Google\ApiCore\ApiException: { "message": "The caller does not have permission", "code": 7, "status": "PERMISSION_DENIED", "details": [ { "@type": 0, "data": "type.googleapis.com\/google.ads.googleads.v2.errors.GoogleAdsFailure" }, { "@type": 0, "data": [ { "errorCode": { "authorizationError": "USER_PERMISSION_DENIED" }, "message": "User doesn't have permission to access customer. Note: If you're accessing a client customer, the manager's customer id must be set in the 'login-customer-id' header. See https:\/\/developers.google.com\/google-ads\/api\/docs\/concepts\/call-structure#login-customer-id"


Code:


<?php
namespace Google\Ads\GoogleAds\Examples\AccountManagement;


include
($_SERVER['DOCUMENT_ROOT'].'/libraries/google-ads/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\V2\GoogleAdsClient;
use Google\Ads\GoogleAds\Lib\V2\GoogleAdsClientBuilder;
use Google\Ads\GoogleAds\Lib\V2\GoogleAdsException;
use Google\Ads\GoogleAds\Lib\OAuth2TokenBuilder;
use Google\Ads\GoogleAds\Util\FieldMasks;
use Google\Ads\GoogleAds\Util\V2\ResourceNames;
use Google\Ads\GoogleAds\V2\Enums\ManagerLinkStatusEnum\ManagerLinkStatus;
use Google\Ads\GoogleAds\V2\Errors\GoogleAdsError;
use Google\Ads\GoogleAds\V2\Resources\CustomerClientLink;
use Google\Ads\GoogleAds\V2\Resources\CustomerManagerLink;
use Google\Ads\GoogleAds\V2\Services\CustomerClientLinkOperation;
use Google\Ads\GoogleAds\V2\Services\CustomerManagerLinkOperation;
use Google\ApiCore\ApiException;
use Google\Protobuf\StringValue;


define
("MANAGER_CUSTOMER_ID", 6170837244);
define
("CUSTOMER_ID", 6083591644);


class LinkManagerToClient {


 
const MANAGER_CUSTOMER_ID = MANAGER_CUSTOMER_ID;
 
const CUSTOMER_ID = CUSTOMER_ID;
 
const PAGE_SIZE = 50;


 
public static function main() {


    $options
= (new ArgumentParser())->parseCommandArguments([
     
ArgumentNames::MANAGER_CUSTOMER_ID => GetOpt::REQUIRED_ARGUMENT,
     
ArgumentNames::CUSTOMER_ID => GetOpt::REQUIRED_ARGUMENT
   
]);


   
try {
     
self::runExample(
        $options
[ArgumentNames::MANAGER_CUSTOMER_ID] ?: self::MANAGER_CUSTOMER_ID,
        $options
[ArgumentNames::CUSTOMER_ID] ?: self::CUSTOMER_ID
     
);
   
} 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) {
        printf
(
         
"\t%s: %s%s",
          $error
->getErrorCode()->getErrorCode(),
          $error
->getMessage(),
          PHP_EOL
       
);
     
}
   
} catch (ApiException $apiException) {
      printf
(
       
"ApiException was thrown with message '%s'.%s",
        $apiException
->getMessage(),
        PHP_EOL
     
);
   
}


 
}


 
public static function runExample(int $managerCustomerId, int $clientCustomerId) {


    $customerClientLinkResourceName
= self::createInvitation($managerCustomerId, $clientCustomerId);


    $managerLinkResourceName
= self::getManagerLinkResourceName($managerCustomerId, $clientCustomerId, $customerClientLinkResourceName);


 
}


 
public static function createInvitation(int $managerCustomerId, int $clientCustomerId) {


    $googleAdsClient
= self::createGoogleAdsClient($managerCustomerId);


    $customerClientLink
= new CustomerClientLink([
     
'client_customer' => new StringValue(['value' => ResourceNames::forCustomer($clientCustomerId)]),
     
'status' => ManagerLinkStatus::PENDING
   
]);


    $customerClientLinkOperation
= new CustomerClientLinkOperation();
    $customerClientLinkOperation
->setCreate($customerClientLink);


    $customerClientLinkServiceClient
= $googleAdsClient->getCustomerClientLinkServiceClient();
    $response
= $customerClientLinkServiceClient->mutateCustomerClientLink($managerCustomerId, $customerClientLinkOperation);


    $customerClientLinkResourceName
= $response->getResult()->getResourceName();


   
return $customerClientLinkResourceName;


 
}


 
public static function getManagerLinkResourceName(int $managerCustomerId, int $clientCustomerId, string $customerClientLinkResourceName) {


    $googleAdsClient
= self::createGoogleAdsClient($managerCustomerId);


    $query
= "SELECT customer_client_link.manager_link_id FROM customer_client_link WHERE customer_client_link.resource_name = '$customerClientLinkResourceName'";


    $googleAdsServiceClient
= $googleAdsClient->getGoogleAdsServiceClient();
    $response
= $googleAdsServiceClient->search(
      $managerCustomerId
,
      $query
,
     
['pageSize' => self::PAGE_SIZE]
   
);


    $managerLinkId
= $response->getIterator()->current()
   
->getCustomerClientLink()
   
->getManagerLinkIdUnwrapped();
    $managerLinkResourceName
= ResourceNames::forCustomerManagerLink($clientCustomerId, $managerCustomerId, $managerLinkId);


   
return $managerLinkResourceName;


 
}


 
private static function createGoogleAdsClient(int $loginCustomerId) {


   
try {


      $oAuth2Credential
= (new OAuth2TokenBuilder())
     
->fromFile()
     
->build();


   
} catch (Exception $e) {


      echo
'Caught exception: ',  $e->getMessage(), "\n";


   
}


   
try {


     
return (new GoogleAdsClientBuilder())
     
->fromFile()
     
->withOAuth2Credential($oAuth2Credential)
     
->withLoginCustomerId($loginCustomerId)
     
->build();


   
} catch (Exception $e) {


      echo
'Caught exception: ',  $e->getMessage(), "\n";


   
}


 
}


}


try {


  $get_data
= new LinkManagerToClient();


  $detail_1
= $get_data->createInvitation(MANAGER_CUSTOMER_ID, CUSTOMER_ID);
  $detail_2
= $get_data->getManagerLinkResourceName(MANAGER_CUSTOMER_ID, CUSTOMER_ID, $detail_1);


} catch (Exception $e) {


  echo
'Caught exception: ',  $e->getMessage(), "\n";


}


Google Ads API Forum Advisor Prod

unread,
Jun 22, 2020, 2:01:03 PM6/22/20
to in...@datadriventool.com, adwor...@googlegroups.com
Hi Damian,

Thank you for reaching out. The USER_PERMISSION_DENIED error indicates that the authorized customer does not have access to the operating customer. Since your OAuth2 credentials were generated for 3191377543, you will have to authenticate your calls from this account, not from 6170837244. Can you confirm if you are trying to manage the accounts with account 3191377543? If so, you will need to specify this account as your loginCustomerId. The "client account" refers to the account being managed by a manager account, so I suggest trying the following: 

define("MANAGER_CUSTOMER_ID", 3191377543);
define("CUSTOMER_ID", 6170837244);

This way, account 3191377543 would be able to manage the manager account 6170837244. 

Let me know if this is what you are trying to accomplish. If not, please elaborate so I can further assist you. Additionally, if you continue to run into issues, kindly provide the complete detailed logs along with the email you are authenticating the API call with. Please "Reply privately to author" when providing this information.

Regards,
Danica, Google Ads API Team

ref:_00D1U1174p._5004Q218Dpr:ref
Reply all
Reply to author
Forward
0 new messages