googleads / google-ads-php

Google Ads API Client Library for PHP
https://developers.google.com/google-ads/api/docs/client-libs/php
Apache License 2.0
277 stars 260 forks source link

Forecast Curves Are Always Empty #578

Closed Infamoustrey closed 3 years ago

Infamoustrey commented 3 years ago

What versions of the client library and Google Ads API are you using?

What environment are you using?

Actions taken

Minimum Repro

$config = [
    'clientId' => '*********',
    'clientSecret' => '*********',
    'refreshToken'  => '*********',
    'developerToken'  => '*********',
    'managerId'  => '*********',
    'keywordPlanResourceName' => '*********',
];

$oAuth2Credential = (new OAuth2TokenBuilder())
    ->withClientId($config['clientId'])
    ->withClientSecret($config['clientSecret'])
    ->withRefreshToken($config['refreshToken'])
    ->build();

$googleClient = (new GoogleAdsClientBuilder())
    ->withOAuth2Credential($oAuth2Credential)
    ->withDeveloperToken($config['developerToken'])
    ->withLoginCustomerId($config['managerId'])
    ->build();

$keywordPlanServiceClient = $googleClient->getKeywordPlanServiceClient();

$response = $keywordPlanServiceClient->generateForecastCurve($config['keywordPlanResourceName']);

foreach ($response->getCampaignForecastCurves() as $curve) {
    foreach ($curve->getMaxCpcBidForecastCurve()->getMaxCpcBidForecasts() as $maxCpcBidForecast) {

        $metric = $maxCpcBidForecast->getMaxCpcBidForecast();
        $maxCpc = $maxCpcBidForecast->getMaxCpcBidMicros();

        printf(
            "Max CPC Bid: %s%s",
            is_null($maxCpc) ? 'null'
                : sprintf("%.2f", round($maxCpc / self::ONE_MILLION, 2)),
            PHP_EOL
        );
        printf(
            "Estimated Clicks: %s%s",
            is_null($metric->getClicks()) ? 'null'
                : sprintf("%.2f", $metric->getClicks()),
            PHP_EOL
        );
        printf(
            "Estimated Cost: %s%s",
            is_null($metric->getCostMicros())
                ? 'null' : sprintf("%.2f", round($metric->getCostMicros() / self::ONE_MILLION, 2)),
            PHP_EOL
        );
        printf(
            "Estimated Cpc: %s%s",
            is_null($metric->getAverageCpc())
                ? 'null' : sprintf("%.2f", round($metric->getAverageCpc() / self::ONE_MILLION, 2)),
            PHP_EOL
        );
    }
}

Expected result

Results from the forecast curves.

Actual result

The forecast curve returned is empty. getCampaignForecastCurves returns an array with a single curve, but drilling into that ->getMaxCpcBidForecastCurve()->getMaxCpcBidForecasts() is always empty. This happens whether the keyword plan was created through the api or through the UI. Alternatively the rest of the API works just fine, so it appears to be limited to just this endpoint.

PierrickVoulet commented 3 years ago

Hi Infamoustrey@. This seems related to the Google Ads API itself, not the library. Could you provide the request and response logs or the request ID so that we can confirm?

Infamoustrey commented 3 years ago

I'd be happy to but I'm not sure which interface would expose the underlying logs or ids. Is there a verbose setting I need to set somewhere to toggle output?

PierrickVoulet commented 3 years ago

You will find our documentation about logging here, feel free to let us know if it does not help.

Infamoustrey commented 3 years ago

Hmm... So I switched to using a file ini based config. And it appears to give the same result but it doesn't seem to respect my logging config. I've ran it several times but it doesn't seem to want to give me a log file.

[OAUTH2]
clientId = "*****"
clientSecret ="*****"
refreshToken = "*****"

[GOOGLE_ADS]
developerToken = "*****"
loginCustomerId = "*****"

[LOGGING]
logFilePath = "/absolute/path/to/project/out.log"
logLevel = "INFO"

I've also update my code to point at this ini file, I know it's using the file because it will throw a permissions error if I remove the token or secret.

$oAuth2Credential = (new OAuth2TokenBuilder())
            ->fromFile(base_path('google_ads_php.ini'))
            ->build();

$googleClient = (new GoogleAdsClientBuilder())
            ->withOAuth2Credential($oAuth2Credential)
            ->fromFile(base_path('google_ads_php.ini'))
            ->build();
PierrickVoulet commented 3 years ago

Could you make sure that you are using gRPC transport (the PHP Extension grpc should be enabled)? You will find more documentation here.

Infamoustrey commented 3 years ago

Alright enabling grpc seemed to fix the logging issue. Below is the output:

[2021-05-12T20:52:33.921917+00:00] google-ads.INFO: Request made: Host: "googleads.googleapis.com", Method: "/google.ads.googleads.v6.services.KeywordPlanService/GenerateForecastCurve", CustomerId: "No customer ID could be extracted from the request", RequestId: "YD9gJcSSP_ibtqMdY_ANXg", IsFault: 0, FaultMessage: "None"  

I'm not too sure what that error/message means, guidance is appreciated.

PierrickVoulet commented 3 years ago

Thanks! This prints information about the Google Ads API call made by the library and IsFault: 0, FaultMessage: "None" means that the Google Ads API returned without any errors.

I was able to confirm that the library behaved as expected: The Google Ads API itself does not return any results. Please contact the support of the Google Ads API, they will help you.