/
AddAdCustomizer.cs
454 lines (388 loc) · 19.9 KB
/
AddAdCustomizer.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
using Google.Ads.GoogleAds.Lib;
using Google.Ads.GoogleAds.V3.Common;
using Google.Ads.GoogleAds.V3.Errors;
using Google.Ads.GoogleAds.V3.Resources;
using Google.Ads.GoogleAds.V3.Services;
using System;
using System.Collections.Generic;
using System.Linq;
using static Google.Ads.GoogleAds.V3.Enums.AdCustomizerPlaceholderFieldEnum.Types;
using static Google.Ads.GoogleAds.V3.Enums.FeedAttributeTypeEnum.Types;
using static Google.Ads.GoogleAds.V3.Enums.PlaceholderTypeEnum.Types;
namespace Google.Ads.GoogleAds.Examples.V3
{
/// <summary>
/// This code example adds an ad customizer feed and associates it with the customer.
/// Then it adds an ad that uses the feed to populate dynamic data.
/// </summary>
public class AddAdCustomizer : ExampleBase
{
/// <summary>
/// Main method, to run this code example as a standalone application.
/// </summary>
/// <param name="args">The command line arguments.</param>
public static void Main(string[] args)
{
AddAdCustomizer codeExample = new AddAdCustomizer();
Console.WriteLine(codeExample.Description);
// The Google Ads customer ID for which the call is made.
long customerId = long.Parse("INSERT_CUSTOMER_ID_HERE");
// ID of the ad group to which ads are added.
long adGroupId1 = long.Parse("INSERT_AD_GROUP_ID_HERE");
// ID of the ad group to which ads are added.
long adGroupId2 = long.Parse("INSERT_AD_GROUP_ID_HERE");
codeExample.Run(new GoogleAdsClient(), customerId, adGroupId1, adGroupId2);
}
/// <summary>
/// Returns a description about the code example.
/// </summary>
public override string Description
{
get
{
return "This code example adds an ad customizer feed and associates it with the " +
"customer. Then it adds an ad that uses the feed to populate dynamic data.";
}
}
/// <summary>
/// Runs the code example.
/// </summary>
/// <param name="client">The Google Ads client.</param>
/// <param name="customerId">The Google Ads customer ID for which the call is made.</param>
/// <param name="adGroupId1">ID of the first ad group to which ad customizers are added.
/// </param>
/// <param name="adGroupId2">ID of the second ad group to which ad customizers are added.
/// </param>
public void Run(GoogleAdsClient client, long customerId, long adGroupId1, long adGroupId2)
{
// Get the AdGroupBidModifierService.
AdGroupBidModifierServiceClient adGroupBidModifierService =
client.GetService(Services.V3.AdGroupBidModifierService);
string feedName = "Ad Customizer example feed " + ExampleUtilities.GetRandomString();
try
{
// Create a feed to be used as the ad customizer.
string adCustomizerFeedResourceName =
CreateAdCustomizerFeed(client, customerId, feedName);
// Retrieve the attributes for the newly created feed.
Dictionary<string, FeedAttribute> adCustomizerFeedAttributes =
GetFeedAttributes(client, customerId, adCustomizerFeedResourceName);
// Map the feed to the ad customizer placeholder type to mark it as an ad customizer.
CreateAdCustomizerMapping(client, customerId, adCustomizerFeedResourceName,
adCustomizerFeedAttributes);
// Create the feed items that will fill the placeholders in the ads customized by the feed.
List<string> feedItemResourceNames = CreateFeedItems(client, customerId,
adCustomizerFeedResourceName, adCustomizerFeedAttributes);
// Create a feed item targeting to associate the feed items with specific ad groups to
// prevent them from being used in other ways.
CreateFeedItemTargets(client, customerId, new[] { adGroupId1, adGroupId2 },
feedItemResourceNames);
// Create ads with the customizations provided by the feed items.
CreateAdsWithCustomizations(client, customerId, new[] { adGroupId1, adGroupId2 },
feedName);
}
catch (GoogleAdsException e)
{
Console.WriteLine("Failure:");
Console.WriteLine($"Message: {e.Message}");
Console.WriteLine($"Failure: {e.Failure}");
Console.WriteLine($"Request ID: {e.RequestId}");
throw;
}
}
/// <summary>
/// Creates a feed to be used for ad customization.
/// </summary>
/// <param name="client">The Google Ads client.</param>
/// <param name="customerId">The Google Ads customer ID for which the call is made.</param>
/// <param name="feedName">Name of the feed.</param>
/// <returns>The resource name of the newly created feed.</returns>
private string CreateAdCustomizerFeed(GoogleAdsClient client, long customerId,
string feedName)
{
// Get the FeedServiceClient.
FeedServiceClient feedService = client.GetService(Services.V3.FeedService);
// Creates three feed attributes: a name, a price and a date. The attribute names
// are arbitrary choices and will be used as placeholders in the ad text fields.
FeedAttribute nameAttribute = new FeedAttribute()
{
Name = "Name",
Type = FeedAttributeType.String
};
FeedAttribute priceAttribute = new FeedAttribute()
{
Name = "Price",
Type = FeedAttributeType.String
};
FeedAttribute dateAttribute = new FeedAttribute()
{
Name = "Date",
Type = FeedAttributeType.DateTime
};
Feed adCustomizerFeed = new Feed()
{
Name = feedName,
Attributes = { nameAttribute, priceAttribute, dateAttribute }
};
FeedOperation feedOperation = new FeedOperation()
{
Create = adCustomizerFeed
};
MutateFeedsResponse response =
feedService.MutateFeeds(customerId.ToString(), new[] { feedOperation });
string feedResourceName = response.Results[0].ResourceName;
Console.WriteLine($"Added feed with resource name '{feedResourceName}'.");
return feedResourceName;
}
/// <summary>
/// Retrieves all the attributes for a feed and returns them in a map using the
/// attribute names as keys.
/// </summary>
/// <param name="client">The Google Ads client.</param>
/// <param name="customerId">The Google Ads customer ID for which the call is made.</param>
/// <param name="feedResourceName">The resource name of the feed.</param>
/// <returns>The attributes of the feed.</returns>
private Dictionary<string, FeedAttribute> GetFeedAttributes(GoogleAdsClient client,
long customerId, string feedResourceName)
{
// Get the GoogleAdsServiceClient.
GoogleAdsServiceClient googleAdsService =
client.GetService(Services.V3.GoogleAdsService);
string query = $"SELECT feed.attributes, feed.name FROM feed WHERE " +
$"feed.resource_name = '{feedResourceName}'";
SearchGoogleAdsRequest request = new SearchGoogleAdsRequest()
{
CustomerId = customerId.ToString(),
Query = query
};
Dictionary<string, FeedAttribute> feedAttributes =
new Dictionary<string, FeedAttribute>();
Feed feed = googleAdsService.Search(request).First().Feed;
Console.WriteLine($"Found the following attributes for feed with name '{feed.Name}'");
foreach (FeedAttribute feedAttribute in feed.Attributes)
{
Console.WriteLine($"\t'{feedAttribute.Name}' with id {feedAttribute.Id} and " +
$"type '{feedAttribute.Type}'");
feedAttributes[feedAttribute.Name] = feedAttribute;
}
return feedAttributes;
}
/// <summary>
/// Creates a feed mapping and sets the feed as an ad customizer feed.
/// </summary>
/// <param name="client">The Google Ads client.</param>
/// <param name="customerId">The Google Ads customer ID for which the call is made.</param>
/// <param name="feedResourceName">The resource name of the feed.</param>
/// <param name="feedAttributes">The attributes of the feed.</param>
private void CreateAdCustomizerMapping(GoogleAdsClient client, long customerId,
string feedResourceName, Dictionary<string, FeedAttribute> feedAttributes)
{
// Get the FeedMappingService.
FeedMappingServiceClient feedMappingService =
client.GetService(Services.V3.FeedMappingService);
// Map the feed attributes to ad customizer placeholder fields.
// For a full list of ad customizer placeholder fields, see
// https://developers.google.com/google-ads/api/reference/rpc/Google.Ads.GoogleAds.V3.enums#Google.Ads.GoogleAds.V3.enums.AdCustomizerPlaceholderFieldEnum.AdCustomizerPlaceholderField
AttributeFieldMapping nameFieldMapping = new AttributeFieldMapping()
{
FeedAttributeId = feedAttributes["Name"].Id,
AdCustomizerField = AdCustomizerPlaceholderField.String
};
AttributeFieldMapping priceFieldMapping = new AttributeFieldMapping()
{
FeedAttributeId = feedAttributes["Price"].Id,
AdCustomizerField = AdCustomizerPlaceholderField.Price
};
AttributeFieldMapping dateFieldMapping = new AttributeFieldMapping()
{
FeedAttributeId = feedAttributes["Date"].Id,
AdCustomizerField = AdCustomizerPlaceholderField.Date
};
FeedMapping feedMapping = new FeedMapping()
{
Feed = feedResourceName,
PlaceholderType = PlaceholderType.AdCustomizer,
AttributeFieldMappings = { nameFieldMapping, priceFieldMapping, dateFieldMapping }
};
FeedMappingOperation operation = new FeedMappingOperation()
{
Create = feedMapping
};
MutateFeedMappingsResponse response =
feedMappingService.MutateFeedMappings(customerId.ToString(), new[] { operation });
Console.WriteLine($"Added feed mapping with resource name" +
$" '{response.Results[0].ResourceName}'.");
}
/// <summary>
/// Creates two different feed items to enable two different ad customizations.
/// </summary>
/// <param name="client">The Google Ads client.</param>
/// <param name="customerId">The Google Ads customer ID for which the call is made.</param>
/// <param name="feedResourceName">The resource name of the feed.</param>
/// <param name="feedAttributes">The attributes of the feed.</param>
/// <returns>The resource names of the feed items.</returns>
private List<string> CreateFeedItems(GoogleAdsClient client, long customerId,
string feedResourceName, Dictionary<string, FeedAttribute> feedAttributes)
{
// Get the FeedItemServiceClient.
FeedItemServiceClient feedItemService =
client.GetService(Services.V3.FeedItemService);
List<FeedItemOperation> feedItemOperations = new List<FeedItemOperation>();
DateTime marsDate = new DateTime(DateTime.Now.Year, DateTime.Now.Month, 1);
feedItemOperations.Add(
CreateFeedItemOperation("Mars", "$1234.56", marsDate.ToString("yyyyMMdd HHmmss"),
feedResourceName, feedAttributes));
DateTime venusDate = new DateTime(DateTime.Now.Year, DateTime.Now.Month, 15);
feedItemOperations.Add(
CreateFeedItemOperation("Venus", "$1450.00", venusDate.ToString("yyyyMMdd HHmmss"),
feedResourceName, feedAttributes));
List<string> feedItemResourceNames = new List<string>();
MutateFeedItemsResponse response =
feedItemService.MutateFeedItems(customerId.ToString(), feedItemOperations);
Console.WriteLine($"Added {response.Results.Count} feed items:");
foreach (MutateFeedItemResult result in response.Results)
{
string feedItemResourceName = result.ResourceName;
feedItemResourceNames.Add(feedItemResourceName);
Console.WriteLine($"Added feed item with resource name '{feedItemResourceName}'.");
}
return feedItemResourceNames;
}
/// <summary>
/// Helper function to create a FeedItemOperation.
/// </summary>
/// <param name="name">The value of the Name attribute.</param>
/// <param name="price">The value of the Price attribute.</param>
/// <param name="date">The value of the Date attribute.</param>
/// <param name="feedResourceName">The resource name of the feed.</param>
/// <param name="feedAttributes">The attributes to be set on the feed.</param>
/// <returns>A FeedItemOperation to create a feed item.</returns>
private FeedItemOperation CreateFeedItemOperation(string name, string price, string date,
string feedResourceName, Dictionary<string, FeedAttribute> feedAttributes)
{
FeedItemAttributeValue nameAttributeValue = new FeedItemAttributeValue()
{
FeedAttributeId = feedAttributes["Name"].Id,
StringValue = name
};
FeedItemAttributeValue priceAttributeValue = new FeedItemAttributeValue()
{
FeedAttributeId = feedAttributes["Price"].Id,
StringValue = price
};
FeedItemAttributeValue dateAttributeValue = new FeedItemAttributeValue()
{
FeedAttributeId = feedAttributes["Date"].Id,
StringValue = date
};
FeedItem feedItem = new FeedItem()
{
Feed = feedResourceName,
AttributeValues = { nameAttributeValue, priceAttributeValue, dateAttributeValue }
};
return new FeedItemOperation()
{
Create = feedItem
};
}
/// <summary>
/// Restricts the feed items to work only with a specific ad group; this prevents the
/// feed items from being used elsewhere and makes sure they are used only for
/// customizing a specific ad group.
/// </summary>
/// <param name="client">The Google Ads client.</param>
/// <param name="customerId">The Google Ads customer ID for which the call is made.</param>
/// <param name="adGroupIds">The ad group IDs to bind the feed items to..</param>
/// <param name="feedItemResourceNames">The resource names of the feed items.</param>
private void CreateFeedItemTargets(GoogleAdsClient client,
long customerId, long[] adGroupIds, List<string> feedItemResourceNames)
{
// Get the FeedItemTargetServiceClient.
FeedItemTargetServiceClient feedItemTargetService =
client.GetService(Services.V3.FeedItemTargetService);
// Bind each feed item to a specific ad group to make sure it will only be used to
// customize ads inside that ad group; using the feed item elsewhere will result
// in an error.
for (int i = 0; i < feedItemResourceNames.Count; i++)
{
string feedItemResourceName = feedItemResourceNames[i];
long adGroupId = adGroupIds[i];
FeedItemTarget feedItemTarget = new FeedItemTarget()
{
AdGroup = ResourceNames.AdGroup(customerId, adGroupId),
FeedItem = feedItemResourceName
};
FeedItemTargetOperation feedItemTargetOperation = new FeedItemTargetOperation()
{
Create = feedItemTarget
};
MutateFeedItemTargetsResponse response =
feedItemTargetService.MutateFeedItemTargets(customerId.ToString(),
new[] { feedItemTargetOperation });
string feedItemTargetResourceName = response.Results[0].ResourceName;
Console.WriteLine($"Added feed item target with resource name " +
$"'{response.Results[0].ResourceName}'.");
}
}
/// <summary>
/// Creates expanded text ads that use the ad customizer feed to populate the placeholders.
/// </summary>
/// <param name="client">The Google Ads client.</param>
/// <param name="customerId">The Google Ads customer ID for which the call is made.</param>
/// <param name="adGroupIds">The ad group IDs in which to create the ads.</param>
/// <param name="feedName">Name of the feed.</param>
private void CreateAdsWithCustomizations(GoogleAdsClient client, long customerId,
long[] adGroupIds, string feedName)
{
// Get the AdGroupAdServiceClient.
AdGroupAdServiceClient adGroupAdService =
client.GetService(Services.V3.AdGroupAdService);
// Creates an expanded text ad using the feed attribute names as placeholders.
Ad ad = new Ad()
{
ExpandedTextAd = new ExpandedTextAdInfo()
{
HeadlinePart1 = $"Luxury cruise to {{={feedName}.Name}}",
HeadlinePart2 = $"Only {{={feedName}.Price}}",
Description = $"Offer ends in {{=countdown({feedName}.Date)}}!"
},
FinalUrls = { "http://www.example.com" }
};
List<AdGroupAdOperation> adGroupAdOperations = new List<AdGroupAdOperation>();
// Creates the same ad in all ad groups. When they serve, they will show
// different values, since they match different feed items.
foreach (long adGroupId in adGroupIds)
{
AdGroupAd adGroupAd = new AdGroupAd()
{
Ad = ad,
AdGroup = ResourceNames.AdGroup(customerId, adGroupId)
};
adGroupAdOperations.Add(new AdGroupAdOperation()
{
Create = adGroupAd
});
}
MutateAdGroupAdsResponse response =
adGroupAdService.MutateAdGroupAds(customerId.ToString(), adGroupAdOperations);
Console.WriteLine($"Added {response.Results.Count} ads:");
foreach (MutateAdGroupAdResult result in response.Results)
{
Console.WriteLine($"Added an ad with resource name '{result.ResourceName}'.");
}
}
}
}