Posts tagged with google-ads-api

The code below is what I'm currently using to generate a JSON representation of the captured data. My question is, is the use of the Google.Protobuf.Reflection.MessageDescriptor and the use of Reflection. The code appears to work. However, is there a better way to do this?

The code is called by a ClearScript-enabled JavaScript instance, thus the strings rather than longs in the parameters.

public string GenerateHistoricalMetrics(GoogleAdsClient client, string customerIdString, string locationIdsList,string languageIdString, string keywordTextsList, string pageUrl, bool debug = true) {     if (debug) Debugger.Launch();     long[] locationIds = (from id in locationIdsList.Split(',') select long.Parse(id)).ToArray();     string[] keywordTexts = keywordTextsList.Split(',');     long customerId = long.Parse(customerIdString);     long languageId = long.Parse(languageIdString);     KeywordPlanIdeaServiceClient keywordPlanIdeaService =         client.GetService(Services.V10.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))     {         return JsonConvert.SerializeObject(new JSON() { Error = "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.     GenerateKeywordIdeasRequest request = new GenerateKeywordIdeasRequest()     {         CustomerId = customerId.ToString(),     };     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         {             Url = pageUrl         };         request.KeywordAndUrlSeed.Keywords.AddRange(keywordTexts);     }     // Create a list of geo target constants based on the resource name of specified     // location IDs.     foreach (long 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 = KeywordPlanNetwork.GoogleSearch; //.GoogleSearchAndPartners;     var list = new List<Dictionary<string, object>>();     try     {         // Generate keyword ideas based on the specified parameters.         var response =             keywordPlanIdeaService.GenerateKeywordIdeas(request);         // Iterate over the results and print its detail.         foreach (GenerateKeywordIdeaResult result in response)         {             KeywordPlanHistoricalMetrics metrics = result.KeywordIdeaMetrics;             Google.Protobuf.Reflection.MessageDescriptor descriptor = GenerateKeywordIdeaResult.Descriptor;             foreach (var field in descriptor.Fields.InDeclarationOrder())             {                 object value = field.Accessor.GetValue(result);                 if (value != null)                 {                     var props = value.GetType().GetProperties(BindingFlags.Public | BindingFlags.GetProperty | BindingFlags.GetField | BindingFlags.Instance);                     var dict = new Dictionary<string, object>();                     foreach (string key in from prop in props                                         let key = Title(field.JsonName) + "." + prop.Name                                         where key.StartsWith("Keyword")                                         select key                     )                     {                         dict.Add(key, value);                     }                     if (dict.Count() > 0)                         list.Add(dict);                 }             }         }     }     catch (GoogleAdsException e)     {         return JsonConvert.SerializeObject(new JSON() { Error = $"Failure: Message: {e.Message}, Failure: {e.Failure}, Request ID: {e.RequestId}" });     }     return JsonConvert.SerializeObject(new JSON() { Cargo = list, Crew = resultList }); } 

I'm on migration from the old Google AdWords API to the new Google Ads API, using PHP-SDK by Google.

This is the use case, where I'm stuck:

I feed an amount of keywords (paginating them by keyword plans a 10k) to generateHistoricalMetrics($keywordPlanResource) and collect the results.

To do so I followed instructions at https://developers.google.com/google-ads/api/docs/keyword-planning/generate-historical-metrics and, especially, https://developers.google.com/google-ads/api/docs/keyword-planning/generate-historical-metrics#mapping_to_the_ui, with using of KeywordPlanAdGroupKeywords (with a single ad group) and avoiding to pass a specific date range for now, relying on the default value.

Further I had to apply some filters on my keywords because of KEYWORD_HAS_INVALID_CHARS and KEYWORD_TEXT_TOO_LONG, but all the errors which I'm aware of are gone now.

Now, I found out, that the KeywordPlanHistoricalMetrics object does not contain any keyword id (of the form customers//keywordPlanAdGroupKeywords/) So, I have to rely on the correct ordering. This is ok as it seems, that the original ordering of keywords is preserved within the results, as here https://developers.google.com/protocol-buffers/docs/encoding#optional

But still I have the problem, that count($keywordPlanServiceClient->generateHistoricalMetrics($keywordPlanResource)->getMetrics()) is lower then count($passedKeywords), where each of $passedKeywords where passed to

new KeywordPlanAdGroupKeyword([ 'text' => $passedKeyword, 'match_type' => KeywordMatchType::EXACT 'keyword_plan_ad_group' => $planAdGroupResource ]); 

Q: So I have two questions here:

  1. Why getMetrics() does not yield the same amount of results as the amount of passed keywords?

  2. I'm struggling with debugging at this moment: Say, I want to know which keywords are let out. Either for providing more information at this place or just to skip them, and let my customer know, that these particular keywords were not queried. How to do this, when although I have a keyword id for every passed keyword I cannot match the returned metrics to them, because the KeywordPlanHistoricalMetrics object does not contain any keyword id.

Detail: While testing I found out, that the reducing of an amount of queried keywords reduces the amount of lost keyword data:

  • 10k of queried keywords - 4,72% loss,
  • 5k - 2,12%,
  • 2,5k - 0,78%,
  • 1,25k - 0,43%,
  • 625 - 0,3%,
  • 500 - 0,24%,
  • 250 - 0,03%
  • 200 - 0,03% of lost keywords.

But I can't imagine, that keywords should be queried one by one.

I have a problem implementing AdMob with my Android app, ads are not showing for my package name, I changed the name and everything works fine, I restored the prod name and everything stopped working with the error: no ad config, this is my first time using AdMob, which means the ads work for a while and then suddenly stop is not the case here, I don't suspect anything wrong with the code because I followed everything in the documentation and, as I said, everything works fine when I change the package name to a random string.

  1. Is app-ads.txt correct? yes, app-ads.txt file found and verified (100% of queries authorized)
  2. Policy center: no current issues, no disapproved apps
  3. App linked to admob? yes it is linked through google play and I noticed the icon is updated
  4. PIN verification: I still didn't reach the verification threshold
  5. Is Google Ads and Adsense linked to Admob? yes, and with the same email
  6. Admob status: Your account is approved
  7. App approval status: Ready (Ad serving enabled)
  8. App stores: Google Play
  9. Ad format: Rewarded
  10. Ads activity performance, Requests: 0 (ZERO)

Note 1: the email I am using on play console is diff from the email of admob / ads / adsense

Note 2: the prod app is already launched in google play store

Any help guys?

MainActivity.java:

package com.example.admob; import androidx.annotation.NonNull; import androidx.appcompat.app.AppCompatActivity; import android.app.Activity; import android.os.Bundle; import android.util.Log; import android.view.View; import android.widget.Toast; import com.google.android.gms.ads.AdRequest; import com.google.android.gms.ads.LoadAdError; import com.google.android.gms.ads.MobileAds; import com.google.android.gms.ads.OnUserEarnedRewardListener; import com.google.android.gms.ads.RequestConfiguration; import com.google.android.gms.ads.initialization.InitializationStatus; import com.google.android.gms.ads.initialization.OnInitializationCompleteListener; import com.google.android.gms.ads.rewarded.RewardItem; import com.google.android.gms.ads.rewarded.RewardedAd; import com.google.android.gms.ads.rewarded.RewardedAdLoadCallback; import java.util.Arrays; public class MainActivity extends AppCompatActivity {     private RewardedAd mRewardedAd;     @Override     protected void onCreate(Bundle savedInstanceState) {         super.onCreate(savedInstanceState);         setContentView(R.layout.activity_main);         /**/         RequestConfiguration configuration = new RequestConfiguration.Builder().setTestDeviceIds(Arrays.asList("PEO7WS709MHDMHS0KA74LQ4KDPL9V8DJ")).build();         /**/         MobileAds.setRequestConfiguration(configuration);         /**/         MobileAds.initialize(this, new OnInitializationCompleteListener() {             @Override             public void onInitializationComplete(InitializationStatus initializationStatus) {             }         });         AdRequest adRequest = new AdRequest.Builder().build();         RewardedAd.load(this, "ca-app-pub-2887021452579791/7518976046",                 adRequest, new RewardedAdLoadCallback() {                     @Override                     public void onAdFailedToLoad(@NonNull LoadAdError loadAdError) {                         // Handle the error.                         Log.d(TAG, loadAdError.getMessage());                         Toast.makeText(MainActivity.this, loadAdError.getMessage(), Toast.LENGTH_SHORT).show();                         mRewardedAd = null;                     }                     @Override                     public void onAdLoaded(@NonNull RewardedAd rewardedAd) {                         mRewardedAd = rewardedAd;                         Log.d(TAG, "Ad was loaded.");                         Toast.makeText(MainActivity.this, "Ad was loaded", Toast.LENGTH_SHORT).show();                     }                 });         findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {             @Override             public void onClick(View view) {                 if (mRewardedAd != null) {                     Activity activityContext = MainActivity.this;                     mRewardedAd.show(activityContext, new OnUserEarnedRewardListener() {                         @Override                         public void onUserEarnedReward(@NonNull RewardItem rewardItem) {                             // Handle the reward.                             Log.d(TAG, "The user earned the reward.");                             Toast.makeText(MainActivity.this, "onUserEarnedReward", Toast.LENGTH_SHORT).show();                         }                     });                 } else {                     Log.d(TAG, "The rewarded ad wasn't ready yet.");                     Toast.makeText(MainActivity.this, "Not ready!", Toast.LENGTH_SHORT).show();                 }             }         });     } } 

Manifest.xml:

<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android"     package="com.example.admob">     <application         android:allowBackup="true"         android:icon="@mipmap/ic_launcher"         android:label="@string/app_name"         android:roundIcon="@mipmap/ic_launcher_round"         android:supportsRtl="true"         android:theme="@style/Theme.AdMob">         <meta-data             android:name="com.google.android.gms.ads.APPLICATION_ID"             android:value="ca-app-pub-2887021452579791~7783129272"/>         <activity             android:name=".MainActivity"             android:exported="true">             <intent-filter>                 <action android:name="android.intent.action.MAIN" />                 <category android:name="android.intent.category.LAUNCHER" />             </intent-filter>         </activity>     </application> </manifest> 

I want to promote my webpage in Google Ads to android phone users , and I need the Google advertising id for each phone to be in my landing page paramter like this. https://example.com/page?gaid=abcdefg

On some other platform , macros are supported so I can set the landing page url as https://example.com/page?gaid={gaid} to promote , but on google ads , I cannot find any explains about macros .