Apology for the late response. That error disappeared since I updated the Google.Ads.GoogleAds library from version 6.1 to the recently release version 7.0.
However, instead of the original error I now get an USER_PERMISSION_DENIED error.
I'm trying this using a manager account (Access level: Test Account. ID: 584-763-xxxx) and a test account (ID: 106-298-xxxx) created under the manager account.
I've specified the test account ID (not manager account) as the LoginCustomerId and got the USER_PERMISSION_DENIED error.
However, when I used the manager count's ID as LoginCustomerId I get this error: DEVELOPER_TOKEN_NOT_APPROVED.
Which of the two account's ID should I use as LoginCustomerId? In my case either way get me (different) errors.
Below is the code to create a GoogleAdsConfig client.
public static GoogleAdsClient Create()
{
var settings = Startup.AppSettings.GoogleAdsApi;
var config = new GoogleAdsConfig
{
DeveloperToken = settings.DeveloperToken,
OAuth2Mode = OAuth2Flow.APPLICATION,
OAuth2ClientId = settings.OAuth2ClientId,
OAuth2ClientSecret = settings.OAuth2ClientSecret,
OAuth2RefreshToken = settings.OAuth2RefreshToken,
LoginCustomerId = settings.LoginCustomerId // ID of test account created under manager account: 106298xxxx
};
return new GoogleAdsClient(config);
}
Below is the example code I've used from the API documentation
public void Run(GoogleAdsClient client, string customerId, long[] locationIds, long languageId, string[] keywordTexts, string pageUrl)
{
var keywordPlanIdeaService = client.GetService(Services.V6.KeywordPlanIdeaService);
// Make sure that keywords and/or page URL were specified. The request must have
// exactly one of urlSeed, keywordSeed, or keywordAndUrlSeed set.
if (keywordTexts.Length == 0 && string.IsNullOrEmpty(pageUrl))
throw new ArgumentException("At least one of keywords or page URL is required, " +
"but neither was specified.");
// Specify the optional arguments of the request as a keywordSeed, UrlSeed,
// or KeywordAndUrlSeed.
var request = new GenerateKeywordIdeasRequest
{
CustomerId = customerId
};
if (keywordTexts.Length == 0)
{
// Only page URL was specified, so use a UrlSeed.
request.UrlSeed = new UrlSeed
{
Url = pageUrl
};
}
else if (string.IsNullOrEmpty(pageUrl))
{
// Only keywords were specified, so use a KeywordSeed.
request.KeywordSeed = new KeywordSeed();
request.KeywordSeed.Keywords.AddRange(keywordTexts);
}
else
{
// Both page URL and keywords were specified, so use a KeywordAndUrlSeed.
request.KeywordAndUrlSeed = new KeywordAndUrlSeed();
request.KeywordAndUrlSeed.Url = pageUrl;
request.KeywordAndUrlSeed.Keywords.AddRange(keywordTexts);
}
// Create a list of geo target constants based on the resource name of specified
// location IDs.
// foreach (var locationId in locationIds)
// request.GeoTargetConstants.Add(ResourceNames.GeoTargetConstant(locationId));
request.Language = ResourceNames.LanguageConstant(languageId);
// Set the network. To restrict to only Google Search, change the parameter below to
// KeywordPlanNetwork.GoogleSearch.
request.KeywordPlanNetwork = KeywordPlanNetworkEnum.Types.KeywordPlanNetwork.GoogleSearchAndPartners;
try
{
// Generate keyword ideas based on the specified parameters.
var response =
keywordPlanIdeaService.GenerateKeywordIdeas(request);
// Iterate over the results and print its detail.
foreach (var result in response)
{
var metrics = result.KeywordIdeaMetrics;
Console.WriteLine($"Keyword idea text '{result.Text}' has " +
$"{metrics.AvgMonthlySearches} average monthly searches and competition " +
$"is {metrics.Competition}.");
}
}
catch (GoogleAdsException e)
{
Console.WriteLine("Failure:");
Console.WriteLine($"Message: {e.Message}");
Console.WriteLine($"Failure: {e.Failure}");
Console.WriteLine($"Request ID: {e.RequestId}");
throw;
}
}