使用PHP调用Google Ads API遭遇NOT_ADS_USER认证错误求助
问题描述
我在使用Google Ads API PHP客户端库结合服务账号JSON文件开发时遇到了问题:
- 已将服务账号邀请至Google Ads账号,但邀请状态始终显示"Awaiting response",且无法登录服务账号接受邀请。
- 运行代码调用API时,抛出
UNAUTHENTICATED错误,错误码显示NOT_ADS_USER。 - 尝试在认证请求中添加
->withImpersonatedEmail($impersonatedEmail)参数(使用同一项目中拥有Google Ads访问权限的账号),问题仍未解决。
调用代码
<?php // Include the Google Ads API PHP client library require_once 'googleads_google-ads-php/vendor/autoload.php'; use Google\Ads\GoogleAds\Lib\V13\GoogleAdsClientBuilder; use Google\Ads\GoogleAds\Lib\V13\GoogleAdsServerStreamDecorator; use Google\Ads\GoogleAds\Util\V13\ResourceNames; use Google\Ads\GoogleAds\V13\Services\GoogleAdsQuery; use Google\Ads\GoogleAds\Lib\OAuth2TokenBuilder; $developerToken = "developerToken"; $jsonKeyFilePath = "json_key.json"; $customerId = "CustomerId"; // Set up authentication using a service account JSON file $googleAdsClient = (new GoogleAdsClientBuilder()) ->withDeveloperToken($developerToken) ->withOAuth2Credential((new OAuth2TokenBuilder()) ->withJsonKeyFilePath($jsonKeyFilePath) ->withScopes(['https://www.googleapis.com/auth/adwords']) ->build()) ->build(); // Define the query to retrieve data from the age_range_view $query = "SELECT segments.date, segments.device, metrics.clicks, ad_group_criterion.criterion_id, ad_group_criterion.display_name FROM age_range_view LIMIT 1000"; try { // Execute the query and get the results $response = $googleAdsClient->getGoogleAdsServiceClient()->search($customerId, $query); // Loop through the rows of data and extract the desired values foreach ($response->iterateAllElements() as $googleAdsRow) { $date = $googleAdsRow->getSegments()->getDate()->getValue(); $device = $googleAdsRow->getSegments()->getDevice()->getValue(); $clicks = $googleAdsRow->getMetrics()->getClicks()->getValue(); $criterionId = $googleAdsRow->getAdGroupCriterion()->getCriterionId()->getValue(); $displayName = $googleAdsRow->getAdGroupCriterion()->getDisplayName()->getValue(); // Print the extracted values to the console printf("Date: %s | Device: %s | Clicks: %d | Criterion ID: %d | Display Name: %s\n", $date, $device, $clicks, $criterionId, $displayName ); } } 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 ); } } catch (ApiException $apiException) { printf("ApiException was thrown with message '%s'.%s", $apiException->getMessage(), PHP_EOL ); } ?>
错误信息
PHP Fatal error: Uncaught Google\ApiCore\ApiException: { "message": "Request is missing required authentication credential. Expected OAuth 2 access token, login cookie or other valid authentication credential. See https:\/\/developers.google.com\/identity\/sign-in\/web\/devconsole-project.", "code": 16, "status": "UNAUTHENTICATED", "details": [ { "@type": "type.googleapis.com\/google.ads.googleads.v13.errors.GoogleAdsFailure", "errors": [ { "errorCode": { "authenticationError": "NOT_ADS_USER" }, "message": "User in the cookie is not a valid Ads user." } ], "requestId": "requestId" } ] } thrown in /data_import/googleads_google-ads-php/vendor/google/gax/src/ApiException.php on line 267
解决步骤
你遗漏了几个关键步骤,按顺序处理:
手动批准服务账号邀请:服务账号是机器账号,没有登录Google Ads界面的权限,必须用Google Ads账号的管理员(真人账号)登录Google Ads后台,进入「访问权限与用户」页面,找到该服务账号的邀请请求,手动点击批准。这是解决
NOT_ADS_USER错误的核心前提。配置服务账号权限:批准后,给服务账号分配合适的角色(比如「标准」或更高权限),确保它能访问你需要查询的资源(比如
age_range_view这类数据视图)。正确使用模拟用户(Impersonation):如果要使用
withImpersonatedEmail,需满足以下条件:- 你的Google Ads账号属于Google Workspace(原G Suite)域。
- 在Google Cloud项目中给服务账号启用「域范围委派」。
- 在Google Workspace后台配置服务账号的API范围,添加
https://www.googleapis.com/auth/adwords。 - 被模拟的邮箱必须是已经在Google Ads账号中拥有访问权限的真人用户。
若你的账号不属于Google Workspace,直接去掉模拟参数,用服务账号本身认证即可(前提是已完成前两步)。
检查代码参数有效性:
$customerId必须是不带横杠的纯数字(比如把123-456-7890改成1234567890)。- 确认
json_key.json路径正确,文件是有效的服务账号密钥,无格式错误。 - 确保
$developerToken是有效的,且与你的Google Ads账号关联。
验证认证流程:可以在代码中添加调试逻辑,打印出获取到的OAuth2令牌,确认令牌有效且未过期。
内容的提问来源于stack exchange,提问作者James
相关产品推荐
相关产品推荐

