The code samples below provide examples of common remarketing functions using the AdWords API. Client Library.
Create a remarketing user list (audience)
// Copyright 2018 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.Api.Ads.AdWords.Lib; using Google.Api.Ads.AdWords.v201809; using System; using System.Collections.Generic; using System.Linq; namespace Google.Api.Ads.AdWords.Examples.CSharp.v201809 { /// <summary> /// This code example illustrates how to create a user list a.k.a. audience. /// </summary> public class AddAudience : 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) { AddAudience codeExample = new AddAudience(); Console.WriteLine(codeExample.Description); try { codeExample.Run(new AdWordsUser()); } catch (Exception e) { Console.WriteLine("An exception occurred while running this code example. {0}", ExampleUtilities.FormatException(e)); } } /// <summary> /// Returns a description about the code example. /// </summary> public override string Description { get { return "This code example illustrates how to create a user list a.k.a. audience."; } } /// <summary> /// Runs the code example. /// </summary> /// <param name="user">The AdWords user.</param> public void Run(AdWordsUser user) { using (AdwordsUserListService userListService = (AdwordsUserListService) user.GetService(AdWordsService.v201809 .AdwordsUserListService)) using (ConversionTrackerService conversionTrackerService = (ConversionTrackerService) user.GetService(AdWordsService.v201809 .ConversionTrackerService)) { BasicUserList userList = new BasicUserList { name = "Mars cruise customers #" + ExampleUtilities.GetRandomString(), description = "A list of mars cruise customers in the last year.", status = UserListMembershipStatus.OPEN, membershipLifeSpan = 365 }; UserListConversionType conversionType = new UserListConversionType { name = userList.name }; userList.conversionTypes = new UserListConversionType[] { conversionType }; // Optional: Set the user list status. userList.status = UserListMembershipStatus.OPEN; // Create the operation. UserListOperation operation = new UserListOperation { operand = userList, @operator = Operator.ADD }; try { // Add the user list. UserListReturnValue retval = userListService.mutate(new UserListOperation[] { operation }); UserList newUserList = retval.value[0]; Console.WriteLine("User list with name '{0}' and id '{1}' was added.", newUserList.name, newUserList.id); List<string> conversionIds = new List<string>(); Array.ForEach(userList.conversionTypes, delegate(UserListConversionType item) { conversionIds.Add(item.id.ToString()); }); // Create the selector. Selector selector = new Selector() { fields = new string[] { ConversionTracker.Fields.Id, ConversionTracker.Fields.GoogleGlobalSiteTag, ConversionTracker.Fields.GoogleEventSnippet }, predicates = new Predicate[] { Predicate.In(ConversionTracker.Fields.Id, conversionIds.ToArray()) } }; // Get all conversion trackers. ConversionTrackerPage page = conversionTrackerService.get(selector); if (page != null && page.entries != null) { foreach (ConversionTracker tracker in page.entries) { Console.WriteLine( "Google global site tag:\n{0}\nGoogle event snippet:\n{1}", tracker.googleGlobalSiteTag, tracker.googleGlobalSiteTag); } } } catch (Exception e) { throw new System.ApplicationException( "Failed to add user lists (a.k.a. audiences).", e); } } } } }
Create an AdWords conversion tracker and add to it upload conversions
// Copyright 2018 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.Api.Ads.AdWords.Lib; using Google.Api.Ads.AdWords.v201809; using System; using System.Collections.Generic; namespace Google.Api.Ads.AdWords.Examples.CSharp.v201809 { /// <summary> /// This code example adds an AdWords conversion tracker and an upload conversion tracker. /// </summary> public class AddConversionTrackers : 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) { AddConversionTrackers codeExample = new AddConversionTrackers(); Console.WriteLine(codeExample.Description); try { codeExample.Run(new AdWordsUser()); } catch (Exception e) { Console.WriteLine("An exception occurred while running this code example. {0}", ExampleUtilities.FormatException(e)); } } /// <summary> /// Returns a description about the code example. /// </summary> public override string Description { get { return "This code example adds an AdWords conversion tracker and an upload " + "conversion tracker."; } } /// <summary> /// Runs the code example. /// </summary> /// <param name="user">The AdWords user.</param> public void Run(AdWordsUser user) { using (ConversionTrackerService conversionTrackerService = (ConversionTrackerService) user.GetService(AdWordsService.v201809 .ConversionTrackerService)) { List<ConversionTracker> conversionTrackers = new List<ConversionTracker>(); // Create an Adwords conversion tracker. AdWordsConversionTracker adWordsConversionTracker = new AdWordsConversionTracker { name = "Earth to Mars Cruises Conversion #" + ExampleUtilities.GetRandomString(), category = ConversionTrackerCategory.DEFAULT, // Set optional fields. status = ConversionTrackerStatus.ENABLED, viewthroughLookbackWindow = 15, defaultRevenueValue = 23.41, alwaysUseDefaultRevenueValue = true }; conversionTrackers.Add(adWordsConversionTracker); // Create an upload conversion for offline conversion imports. UploadConversion uploadConversion = new UploadConversion { // Set an appropriate category. This field is optional, and will be set to // DEFAULT if not mentioned. category = ConversionTrackerCategory.LEAD, name = "Upload Conversion #" + ExampleUtilities.GetRandomString(), viewthroughLookbackWindow = 30, ctcLookbackWindow = 90, // Optional: Set the default currency code to use for conversions // that do not specify a conversion currency. This must be an ISO 4217 // 3-character currency code such as "EUR" or "USD". // If this field is not set on this UploadConversion, AdWords will use // the account's currency. defaultRevenueCurrencyCode = "EUR", // Optional: Set the default revenue value to use for conversions // that do not specify a conversion value. Note that this value // should NOT be in micros. defaultRevenueValue = 2.50 }; // Optional: To upload fractional conversion credits, mark the upload conversion // as externally attributed. See // https://developers.google.com/adwords/api/docs/guides/conversion-tracking#importing_externally_attributed_conversions // to learn more about importing externally attributed conversions. // uploadConversion.isExternallyAttributed = true; conversionTrackers.Add(uploadConversion); try { // Create operations. List<ConversionTrackerOperation> operations = new List<ConversionTrackerOperation>(); foreach (ConversionTracker conversionTracker in conversionTrackers) { operations.Add(new ConversionTrackerOperation() { @operator = Operator.ADD, operand = conversionTracker }); } // Add conversion tracker. ConversionTrackerReturnValue retval = conversionTrackerService.mutate(operations.ToArray()); // Display the results. if (retval != null && retval.value != null) { foreach (ConversionTracker conversionTracker in retval.value) { Console.WriteLine( "Conversion with ID {0}, name '{1}', status '{2}' and " + "category '{3}' was added.", conversionTracker.id, conversionTracker.name, conversionTracker.status, conversionTracker.category); if (conversionTracker is AdWordsConversionTracker) { AdWordsConversionTracker newAdWordsConversionTracker = (AdWordsConversionTracker) conversionTracker; Console.WriteLine( "Google global site tag:\n{0}\nGoogle event snippet:\n{1}", newAdWordsConversionTracker.googleGlobalSiteTag, newAdWordsConversionTracker.googleEventSnippet); } } } else { Console.WriteLine("No conversion trackers were added."); } } catch (Exception e) { throw new System.ApplicationException("Failed to add conversion trackers.", e); } } } } }
Create and populate a user list
// Copyright 2018 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.Api.Ads.AdWords.Lib; using Google.Api.Ads.AdWords.v201809; using System; using System.Collections.Generic; using System.Security.Cryptography; using System.Text; namespace Google.Api.Ads.AdWords.Examples.CSharp.v201809 { /// <summary> /// This code example adds a user list (a.k.a. audience) and uploads hashed /// email addresses to populate the list. /// /// <p> /// <em>Note:</em> It may take up to several hours for the list to be /// populated with members. Email addresses must be associated with a Google /// account. For privacy purposes, the user list size will show as zero until /// the list has at least 1000 members. After that, the size will be rounded /// to the two most significant digits. /// </p> /// </summary> public class AddCrmBasedUserList : ExampleBase { private static readonly string[] EMAILS = new string[] { "customer1@example.com", "customer2@example.com", " Customer3@example.com " }; private const string FIRST_NAME = "John"; private const string LAST_NAME = "Doe"; private const string COUNTRY_CODE = "US"; private const string ZIP_CODE = "10001"; private SHA256 digest = SHA256.Create(); /// <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) { AddCrmBasedUserList codeExample = new AddCrmBasedUserList(); Console.WriteLine(codeExample.Description); try { codeExample.Run(new AdWordsUser()); } catch (Exception e) { Console.WriteLine("An exception occurred while running this code example. {0}", ExampleUtilities.FormatException(e)); } } /// <summary> /// Returns a description about the code example. /// </summary> public override string Description { get { return "This code example adds a user list (a.k.a. audience) and " + "uploads hashed email addresses to populate the list."; } } /// <summary> /// Runs the code example. /// </summary> /// <param name="user">The AdWords user.</param> public void Run(AdWordsUser user) { using (AdwordsUserListService userListService = (AdwordsUserListService) user.GetService(AdWordsService.v201809 .AdwordsUserListService)) { // Create a user list. CrmBasedUserList userList = new CrmBasedUserList() { name = "Customer relationship management list #" + ExampleUtilities.GetRandomString(), description = "A list of customers that originated from email addresses", // CRM - based user lists can use a membershipLifeSpan of 10000 to indicate // unlimited; otherwise normal values apply. membershipLifeSpan = 30L, uploadKeyType = CustomerMatchUploadKeyType.CONTACT_INFO }; // Create operation. UserListOperation operation = new UserListOperation() { operand = userList, @operator = Operator.ADD }; try { // Add user list. UserListReturnValue result = userListService.mutate(new UserListOperation[] { operation }); Console.WriteLine( "Created new user list with name = '{0}' and id = " + "'{1}'.", result.value[0].name, result.value[0].id); // Get user list ID. long userListId = result.value[0].id; // Prepare the emails for upload. List<Member> memberList = new List<Member>(); // Hash normalized email addresses based on SHA-256 hashing algorithm. string[] emailHashes = new string[EMAILS.Length]; for (int i = 0; i < EMAILS.Length; i++) { Member member = new Member { hashedEmail = ToSha256String(digest, ToNormalizedEmail(EMAILS[i])) }; memberList.Add(member); } ; // Add a user by first and last name. AddressInfo addressInfo = new AddressInfo { // First and last name must be normalized and hashed. hashedFirstName = ToSha256String(digest, FIRST_NAME), hashedLastName = ToSha256String(digest, LAST_NAME), // Country code and zip code are sent in plaintext. zipCode = ZIP_CODE, countryCode = COUNTRY_CODE }; Member memberByAddress = new Member { addressInfo = addressInfo }; memberList.Add(memberByAddress); // Create operation to add members to the user list based on email // addresses. MutateMembersOperation mutateMembersOperation = new MutateMembersOperation() { operand = new MutateMembersOperand() { userListId = userListId, membersList = memberList.ToArray() }, @operator = Operator.ADD }; // Add members to the user list based on email addresses. MutateMembersReturnValue mutateMembersResult = userListService.mutateMembers( new MutateMembersOperation[] { mutateMembersOperation }); // Display results. // Reminder: it may take several hours for the list to be populated // with members. foreach (UserList userListResult in mutateMembersResult.userLists) { Console.WriteLine( "Email addresses were added to user list with " + "name '{0}' and id '{1}'.", userListResult.name, userListResult.id); } } catch (Exception e) { throw new System.ApplicationException( "Failed to add user lists " + "(a.k.a. audiences) and upload email addresses.", e); } } } /// <summary> /// Hash email address using SHA-256 hashing algorithm. /// </summary> /// <param name="digest">Provides the algorithm for SHA-256.</param> /// <param name="email">The email address to hash.</param> /// <returns>Hash email address using SHA-256 hashing algorithm.</returns> private static string ToSha256String(SHA256 digest, string email) { byte[] digestBytes = digest.ComputeHash(Encoding.UTF8.GetBytes(email)); // Convert the byte array into an unhyphenated hexadecimal string. return BitConverter.ToString(digestBytes).Replace("-", string.Empty); } /// <summary> /// Removes leading and trailing whitespace and converts all characters to /// lower case. /// </summary> /// <param name="email">The email address to normalize.</param> /// <returns>A normalized copy of the string.</returns> private static string ToNormalizedEmail(string email) { return email.Trim().ToLower(); } } }
Create rule-based user lists
// Copyright 2018 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.Api.Ads.AdWords.Lib; using Google.Api.Ads.AdWords.v201809; using System; using System.Collections.Generic; namespace Google.Api.Ads.AdWords.Examples.CSharp.v201809 { /// <summary> /// This code example adds two rule-based remarketing user lists: one with no /// site visit date restrictions, and another that will only include users /// who visit your site in the next six months. See /// https://developers.google.com/adwords/api/docs/guides/rule-based-remarketing /// to learn more about rule based remarketing. /// </summary> public class AddRuleBasedRemarketingList : ExampleBase { private const string DATE_FORMAT_STRING = "yyyyMMdd"; /// <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) { AddRuleBasedRemarketingList codeExample = new AddRuleBasedRemarketingList(); Console.WriteLine(codeExample.Description); try { codeExample.Run(new AdWordsUser()); } catch (Exception e) { Console.WriteLine("An exception occurred while running this code example. {0}", ExampleUtilities.FormatException(e)); } } /// <summary> /// Returns a description about the code example. /// </summary> public override string Description { get { return "This code example adds two rule-based remarketing user lists: one with " + "no site visit date restrictions, and another that will only include users " + "who visit your site in the next six months. See " + "https://developers.google.com/adwords/api/docs/guides/rule-based-remarketing" + " to learn more about rule based remarketing."; } } /// <summary> /// Runs the code example. /// </summary> /// <param name="user">The AdWords user.</param> public void Run(AdWordsUser user) { using (AdwordsUserListService userListService = (AdwordsUserListService) user.GetService(AdWordsService.v201809 .AdwordsUserListService)) { // First rule item group - users who visited the checkout page and had // more than one item in their shopping cart. StringRuleItem checkoutStringRuleItem = new StringRuleItem { key = new StringKey { name = "ecomm_pagetype" }, op = StringRuleItemStringOperator.EQUALS, value = "checkout" }; RuleItem checkoutRuleItem = new RuleItem { Item = checkoutStringRuleItem }; NumberRuleItem cartSizeNumberRuleItem = new NumberRuleItem { key = new NumberKey { name = "cartsize" }, op = NumberRuleItemNumberOperator.GREATER_THAN, value = 1 }; RuleItem cartSizeRuleItem = new RuleItem { Item = cartSizeNumberRuleItem }; // Combine the two rule items into a RuleItemGroup so AdWords will AND // their rules together. RuleItemGroup checkoutMultipleItemGroup = new RuleItemGroup { items = new RuleItem[] { checkoutRuleItem, cartSizeRuleItem } }; // Second rule item group - users who check out within the next 3 months. DateRuleItem startDateDateRuleItem = new DateRuleItem { key = new DateKey { name = "checkoutdate" }, op = DateRuleItemDateOperator.AFTER, value = DateTime.Now.ToString(DATE_FORMAT_STRING) }; RuleItem startDateRuleItem = new RuleItem { Item = startDateDateRuleItem }; DateRuleItem endDateDateRuleItem = new DateRuleItem { key = new DateKey { name = "checkoutdate" }, op = DateRuleItemDateOperator.BEFORE, value = DateTime.Now.AddMonths(3).ToString(DATE_FORMAT_STRING) }; RuleItem endDateRuleItem = new RuleItem { Item = endDateDateRuleItem }; // Combine the date rule items into a RuleItemGroup. RuleItemGroup checkedOutNextThreeMonthsItemGroup = new RuleItemGroup { items = new RuleItem[] { startDateRuleItem, endDateRuleItem } }; // Combine the rule item groups into a Rule so AdWords knows how to apply the rules. Rule rule = new Rule { groups = new RuleItemGroup[] { checkoutMultipleItemGroup, checkedOutNextThreeMonthsItemGroup }, // ExpressionRuleUserLists can use either CNF Or DNF For matching. CNF means // 'at least one item in each rule item group must match', and DNF means 'at // least one entire rule item group must match'. // DateSpecificRuleUserList only supports DNF. You can also omit the rule // type altogether To Default To DNF. ruleType = UserListRuleTypeEnumsEnum.DNF }; // Third and fourth rule item groups. // Visitors of a page who visited another page. See // https://developers.google.com/adwords/api/docs/reference/latest/AdwordsUserListService.StringKey // for more details. StringKey urlStringKey = new StringKey() { name = "url__" }; StringRuleItem site1StringRuleItem = new StringRuleItem { key = urlStringKey, op = StringRuleItemStringOperator.EQUALS, value = "example.com/example1" }; RuleItem site1RuleItem = new RuleItem { Item = site1StringRuleItem }; StringRuleItem site2StringRuleItem = new StringRuleItem { key = (urlStringKey), op = (StringRuleItemStringOperator.EQUALS), value = ("example.com/example2") }; RuleItem site2RuleItem = new RuleItem { Item = (site2StringRuleItem) }; // Create two RuleItemGroups to show that a visitor browsed two sites. RuleItemGroup site1RuleItemGroup = new RuleItemGroup { items = new RuleItem[] { site1RuleItem } }; RuleItemGroup site2RuleItemGroup = new RuleItemGroup { items = new RuleItem[] { site2RuleItem } }; // Create two rules to show that a visitor browsed two sites. Rule userVisitedSite1Rule = new Rule { groups = new RuleItemGroup[] { site1RuleItemGroup } }; Rule userVisitedSite2Rule = new Rule { groups = new RuleItemGroup[] { site2RuleItemGroup } }; // Create the user list with no restrictions on site visit date. ExpressionRuleUserList expressionUserList = new ExpressionRuleUserList(); string creationTimeString = DateTime.Now.ToString("yyyyMMdd_HHmmss"); expressionUserList.name = "Expression based user list created at " + creationTimeString; expressionUserList.description = "Users who checked out in three month window OR " + "visited the checkout page with more than one item in their cart."; expressionUserList.rule = rule; // Optional: Set the prepopulationStatus to REQUESTED to include past users // in the user list. expressionUserList.prepopulationStatus = RuleBasedUserListPrepopulationStatus.REQUESTED; // Create the user list restricted to users who visit your site within // the next six months. DateTime startDate = DateTime.Now; DateTime endDate = startDate.AddMonths(6); DateSpecificRuleUserList dateUserList = new DateSpecificRuleUserList { name = "Date rule user list created at " + creationTimeString, description = string.Format( "Users who visited the site between {0} and " + "{1} and checked out in three month window OR visited the checkout page " + "with more than one item in their cart.", startDate.ToString(DATE_FORMAT_STRING), endDate.ToString(DATE_FORMAT_STRING)), rule = rule, // Set the start and end dates of the user list. startDate = startDate.ToString(DATE_FORMAT_STRING), endDate = endDate.ToString(DATE_FORMAT_STRING) }; // Create the user list where "Visitors of a page who did visit another page". // To create a user list where "Visitors of a page who did not visit another // page", change the ruleOperator from AND to AND_NOT. CombinedRuleUserList combinedRuleUserList = new CombinedRuleUserList { name = "Combined rule user list created at " + creationTimeString, description = "Users who visited two sites.", leftOperand = userVisitedSite1Rule, rightOperand = userVisitedSite2Rule, ruleOperator = CombinedRuleUserListRuleOperator.AND }; // Create operations to add the user lists. List<UserListOperation> operations = new List<UserListOperation>(); foreach (UserList userList in new UserList[] { expressionUserList, dateUserList, combinedRuleUserList }) { UserListOperation operation = new UserListOperation { operand = userList, @operator = Operator.ADD }; operations.Add(operation); } try { // Submit the operations. UserListReturnValue result = userListService.mutate(operations.ToArray()); // Display the results. foreach (UserList userListResult in result.value) { Console.WriteLine( "User list added with ID {0}, name '{1}', status '{2}', " + "list type '{3}', accountUserListStatus '{4}', description '{5}'.", userListResult.id, userListResult.name, userListResult.status, userListResult.listType, userListResult.accountUserListStatus, userListResult.description); } } catch (Exception e) { throw new System.ApplicationException("Failed to add rule based user lists.", e); } } } } }
Import conversion adjustments for existing conversions
// Copyright 2018 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.Api.Ads.AdWords.Lib; using Google.Api.Ads.AdWords.v201809; using System; namespace Google.Api.Ads.AdWords.Examples.CSharp.v201809 { /// <summary> /// This code example demonstrates adjusting one conversion, but you can add more than one /// operation in a single mutate request. /// </summary> public class UploadOfflineConversionAdjustments : 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) { UploadOfflineConversionAdjustments codeExample = new UploadOfflineConversionAdjustments(); Console.WriteLine(codeExample.Description); try { string conversionName = "INSERT_CONVERSION_NAME_HERE"; string gclid = "INSERT_GOOGLE_CLICK_ID_HERE"; string conversionTime = "INSERT_CONVERSION_TIME_HERE"; OfflineConversionAdjustmentType adjustmentType = (OfflineConversionAdjustmentType) Enum.Parse( typeof(OfflineConversionAdjustmentType), "INSERT_ADJUSTMENT_TYPE_HERE"); string adjustmentTime = "INSERT_ADJUSTMENT_TIME_HERE"; double adjustedValue = double.Parse("INSERT_ADJUSTED_VALUE_HERE"); codeExample.Run(new AdWordsUser(), conversionName, gclid, conversionTime, adjustmentType, adjustmentTime, adjustedValue); } catch (Exception e) { Console.WriteLine("An exception occurred while running this code example. {0}", ExampleUtilities.FormatException(e)); } } /// <summary> /// Returns a description about the code example. /// </summary> public override string Description { get { return "This code example demonstrates adjusting one conversion, but you can add " + "more than one operation in a single mutate request."; } } /// <summary> /// Runs the code example. /// </summary> /// <param name="user">The AdWords user.</param> /// <param name="conversionName">Name of the conversion to make adjustments.</param> /// <param name="gclid">The google click ID for the adjustment.</param> /// <param name="conversionTime">The conversion time.</param> /// <param name="adjustmentType">The type of conversion adjustment.</param> /// <param name="adjustmentTime">The conversion adjustment time.</param> /// <param name="adjustedValue">The conversion adjustment value.</param> public void Run(AdWordsUser user, string conversionName, string gclid, string conversionTime, OfflineConversionAdjustmentType adjustmentType, string adjustmentTime, double adjustedValue) { using (OfflineConversionAdjustmentFeedService service = (OfflineConversionAdjustmentFeedService) user.GetService(AdWordsService.v201809 .OfflineConversionAdjustmentFeedService)) { // Associate conversion adjustments with the existing named conversion // tracker. The GCLID should have been uploaded before with a // conversion. GclidOfflineConversionAdjustmentFeed feed = new GclidOfflineConversionAdjustmentFeed() { conversionName = conversionName, googleClickId = gclid, conversionTime = conversionTime, adjustmentType = adjustmentType, adjustmentTime = adjustmentTime, adjustedValue = adjustedValue }; // Create the operation. var operation = new OfflineConversionAdjustmentFeedOperation() { @operator = Operator.ADD, operand = feed }; try { // Issue a request to the servers for adjustments of the conversion. OfflineConversionAdjustmentFeedReturnValue retval = service.mutate( new OfflineConversionAdjustmentFeedOperation[] { operation }); GclidOfflineConversionAdjustmentFeed updatedFeed = (GclidOfflineConversionAdjustmentFeed) retval.value[0]; Console.WriteLine( "Uploaded conversion adjustment value of '{0}' for Google " + "Click ID '{1}'.", updatedFeed.conversionName, updatedFeed.googleClickId); } catch (Exception e) { throw new System.ApplicationException("Failed to update conversion adjustment.", e); } } } } }
Import offline call conversions
// Copyright 2018 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.Api.Ads.AdWords.Lib; using Google.Api.Ads.AdWords.v201809; using System; namespace Google.Api.Ads.AdWords.Examples.CSharp.v201809 { /// <summary> /// This code example imports offline call conversion values for calls related to the /// ads in your account. /// </summary> public class UploadOfflineCallConversions : 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) { string conversionName = "INSERT_CONVERSION_NAME_HERE"; // For times use the format yyyyMMdd HHmmss tz. For more details on formats, see: // https://developers.google.com/adwords/api/docs/appendix/codes-formats#date-and-time-formats // For time zones, see: // https://developers.google.com/adwords/api/docs/appendix/codes-formats#timezone-ids // The conversion time should be after the call start time. string conversionTime = "INSERT_CONVERSION_TIME_HERE"; string callStartTime = "INSERT_CALL_START_TIME_HERE"; string callerId = "INSERT_CALLER_ID_HERE"; double conversionValue = double.Parse("INSERT_CONVERSION_VALUE_HERE"); UploadOfflineCallConversions codeExample = new UploadOfflineCallConversions(); Console.WriteLine(codeExample.Description); try { codeExample.Run(new AdWordsUser(), conversionName, callStartTime, callerId, conversionTime, conversionValue); } catch (Exception e) { Console.WriteLine("An exception occurred while running this code example. {0}", ExampleUtilities.FormatException(e)); } } /// <summary> /// Returns a description about the code example. /// </summary> public override string Description { get { return "This code example imports offline call conversion values for calls related " + "to the ads in your account."; } } /// <summary> /// Runs the code example. /// </summary> /// <param name="user">The AdWords user.</param> /// <param name="conversionName">The name of the call conversion to be updated.</param> /// <param name="callStartTime">The call start time.</param> /// <param name="conversionValue">The conversion value to be uploaded.</param> /// <param name="callerId">The caller ID to be uploaded.</param> /// <param name="conversionTime">The conversion time, in yyyymmdd hhmmss /// format.</param> public void Run(AdWordsUser user, string conversionName, string callStartTime, string callerId, string conversionTime, double conversionValue) { using (OfflineCallConversionFeedService offlineCallConversionFeedService = (OfflineCallConversionFeedService) user.GetService(AdWordsService.v201809 .OfflineCallConversionFeedService)) { // Associate offline call conversions with the existing named conversion tracker. // If this tracker was newly created, it may be a few hours before it can accept // conversions. OfflineCallConversionFeed feed = new OfflineCallConversionFeed { callerId = callerId, callStartTime = callStartTime, conversionName = conversionName, conversionTime = conversionTime, conversionValue = conversionValue }; OfflineCallConversionFeedOperation offlineCallConversionOperation = new OfflineCallConversionFeedOperation { @operator = Operator.ADD, operand = feed }; try { // This example uploads only one call conversion, but you can upload // multiple call conversions by passing additional operations. OfflineCallConversionFeedReturnValue offlineCallConversionReturnValue = offlineCallConversionFeedService.mutate( new OfflineCallConversionFeedOperation[] { offlineCallConversionOperation }); // Display results. foreach (OfflineCallConversionFeed feedResult in offlineCallConversionReturnValue.value) { Console.WriteLine( "Uploaded offline call conversion value of {0} for caller ID '{1}'.", feedResult.conversionValue, feedResult.callerId); } } catch (Exception e) { throw new System.ApplicationException( "Failed to upload offline call conversions.", e); } } } } }
Import offline click conversions
// Copyright 2018 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.Api.Ads.AdWords.Lib; using Google.Api.Ads.AdWords.v201809; using System; namespace Google.Api.Ads.AdWords.Examples.CSharp.v201809 { /// <summary> /// This code example imports offline conversion values for specific clicks to /// your account. To get Google Click ID for a click, run /// CLICK_PERFORMANCE_REPORT. To set up a conversion tracker, run the /// AddConversionTrackers.cs example. /// </summary> public class UploadOfflineConversions : 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) { string conversionName = "INSERT_CONVERSION_NAME_HERE"; // GCLID needs to be newer than 30 days. string gClId = "INSERT_GOOGLE_CLICK_ID_HERE"; // The conversion time should be higher than the click time. string conversionTime = "INSERT_CONVERSION_TIME_HERE"; double conversionValue = double.Parse("INSERT_CONVERSION_VALUE_HERE"); UploadOfflineConversions codeExample = new UploadOfflineConversions(); Console.WriteLine(codeExample.Description); try { codeExample.Run(new AdWordsUser(), conversionName, gClId, conversionTime, conversionValue); } catch (Exception e) { Console.WriteLine("An exception occurred while running this code example. {0}", ExampleUtilities.FormatException(e)); } } /// <summary> /// Returns a description about the code example. /// </summary> public override string Description { get { return "This code example imports offline conversion values for specific clicks " + "to your account. To get Google Click ID for a click, run " + "CLICK_PERFORMANCE_REPORT. To set up a conversion tracker, run the " + "AddConversionTrackers.cs example."; } } /// <summary> /// Runs the code example. /// </summary> /// <param name="user">The AdWords user.</param> /// <param name="conversionName">The name of the upload conversion to be /// created.</param> /// <param name="gClid">The Google Click ID of the click for which offline /// conversions are uploaded.</param> /// <param name="conversionValue">The conversion value to be uploaded. /// </param> /// <param name="conversionTime">The conversion time, in yyyymmdd hhmmss /// format.</param> public void Run(AdWordsUser user, string conversionName, string gClid, string conversionTime, double conversionValue) { using (OfflineConversionFeedService offlineConversionFeedService = (OfflineConversionFeedService) user.GetService(AdWordsService.v201809 .OfflineConversionFeedService)) { try { // Associate offline conversions with the existing named conversion tracker. If // this tracker was newly created, it may be a few hours before it can accept // conversions. OfflineConversionFeed feed = new OfflineConversionFeed { conversionName = conversionName, conversionTime = conversionTime, conversionValue = conversionValue, googleClickId = gClid }; // Optional: To upload fractional conversion credits, set the external // attribution model and credit. To use this feature, your conversion tracker // should be marked as externally attributed. See // https://developers.google.com/adwords/api/docs/guides/conversion-tracking#importing_externally_attributed_conversions // to learn more about importing externally attributed conversions. // feed.externalAttributionModel = "Linear"; // feed.externalAttributionCredit = 0.3; OfflineConversionFeedOperation offlineConversionOperation = new OfflineConversionFeedOperation { @operator = Operator.ADD, operand = feed }; OfflineConversionFeedReturnValue offlineConversionRetval = offlineConversionFeedService.mutate(new OfflineConversionFeedOperation[] { offlineConversionOperation }); OfflineConversionFeed newFeed = offlineConversionRetval.value[0]; Console.WriteLine( "Uploaded offline conversion value of {0} for Google Click ID = " + "'{1}' to '{2}'.", newFeed.conversionValue, newFeed.googleClickId, newFeed.conversionName); } catch (Exception e) { throw new System.ApplicationException("Failed upload offline conversions.", e); } } } } }
Upload offline data for store sales transactions
// Copyright 2018 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.Api.Ads.AdWords.Lib; using Google.Api.Ads.AdWords.v201809; using System; using System.Collections.Generic; using System.Security.Cryptography; using System.Text; namespace Google.Api.Ads.AdWords.Examples.CSharp.v201809 { /// <summary> /// This code example shows how to upload offline data for store sales transactions. /// </summary> public class UploadOfflineData : ExampleBase { private SHA256 digest = SHA256.Create(); /// <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) { // The external upload ID can be any number that you use to keep track of your uploads. long externalUploadId = long.Parse("INSERT_EXTERNAL_UPLOAD_ID"); // Insert the conversion type name that you'd like to attribute this upload to. string conversionName = "INSERT_CONVERSION_NAME"; // Insert email addresses below for creating user identifiers. string[] emailAddresses = { "EMAIL_ADDRESS_1", "EMAIL_ADDRESS_2" }; // Insert advertiser upload time. // For times, use the format yyyyMMdd HHmmss tz. For // more details on formats, see: // https://developers.google.com/adwords/api/docs/appendix/codes-formats#date-and-time-formats // For time zones, see: // https://developers.google.com/adwords/api/docs/appendix/codes-formats#timezone-ids string advertiserUploadTime = "INSERT_ADVERTISER_UPLOAD_TIME"; // Insert bridge map version ID. string bridgeMapVersionId = "INSERT_BRIDGEMAP_VERSION_ID"; // Insert partner ID. int partnerId = int.Parse("INSERT_PARTNER_ID"); // Specify the upload type (STORE_SALES_UPLOAD_FIRST_PARTY or // STORE_SALES_UPLOAD_THIRD_PARTY) OfflineDataUploadType uploadType = (OfflineDataUploadType) Enum.Parse(typeof(OfflineDataUploadType), "INSERT_UPLOAD_TYPE"); UploadOfflineData codeExample = new UploadOfflineData(); Console.WriteLine(codeExample.Description); try { codeExample.Run(new AdWordsUser(), conversionName, externalUploadId, emailAddresses, advertiserUploadTime, bridgeMapVersionId, uploadType, partnerId); } catch (Exception e) { Console.WriteLine("An exception occurred while running this code example. {0}", ExampleUtilities.FormatException(e)); } } /// <summary> /// Returns a description about the code example. /// </summary> public override string Description { get { return "This code example shows how to upload offline data for store sales " + "transactions."; } } /// <summary> /// Runs the code example. /// </summary> /// <param name="user">The AdWords user.</param> /// <param name="conversionName">The conversion type name that you'd like to attribute this /// upload to.</param> /// <param name="externalUploadId">The external upload ID can be any number that you use to /// keep track of your uploads.</param> /// <param name="emailAddresses">The email addresses for creating user identifiers.</param> /// <param name="advertiserUploadTime">The advertiser upload time. For times, use the format /// yyyyMMdd HHmmss tz. For more details on formats, see: /// https://developers.google.com/adwords/api/docs/appendix/codes-formats#date-and-time-formats /// For time zones, see: /// https://developers.google.com/adwords/api/docs/appendix/codes-formats#timezone-ids /// </param> /// <param name="bridgeMapVersionId">The version ID of the bridge map.</param> /// <param name="uploadType">The type of data upload.</param> /// <param name="partnerId">The partner ID</param> public void Run(AdWordsUser user, string conversionName, long externalUploadId, string[] emailAddresses, string advertiserUploadTime, string bridgeMapVersionId, OfflineDataUploadType uploadType, int partnerId) { using (OfflineDataUploadService offlineDataUploadService = (OfflineDataUploadService) user.GetService(AdWordsService.v201809 .OfflineDataUploadService)) { offlineDataUploadService.RequestHeader.partialFailure = true; // Create the first offline data row for upload. // This transaction occurred 7 days ago with amount of 200 USD. DateTime transactionTime1 = DateTime.Now; transactionTime1.AddDays(-7); long transactionAmount1 = 200000000; string transactionCurrencyCode1 = "USD"; UserIdentifier[] userIdentifierList1 = new UserIdentifier[] { CreateUserIdentifier(OfflineDataUploadUserIdentifierType.HASHED_EMAIL, emailAddresses[0]), CreateUserIdentifier(OfflineDataUploadUserIdentifierType.STATE, "New York") }; OfflineData offlineData1 = CreateOfflineDataRow(transactionTime1, transactionAmount1, transactionCurrencyCode1, conversionName, userIdentifierList1); // Create the second offline data row for upload. // This transaction occurred 14 days ago with amount of 450 EUR. DateTime transactionTime2 = DateTime.Now; transactionTime2.AddDays(-14); long transactionAmount2 = 450000000; string transactionCurrencyCode2 = "EUR"; UserIdentifier[] userIdentifierList2 = new UserIdentifier[] { CreateUserIdentifier(OfflineDataUploadUserIdentifierType.HASHED_EMAIL, emailAddresses[1]), CreateUserIdentifier(OfflineDataUploadUserIdentifierType.STATE, "California") }; OfflineData offlineData2 = CreateOfflineDataRow(transactionTime2, transactionAmount2, transactionCurrencyCode2, conversionName, userIdentifierList2); // Create offline data upload object. OfflineDataUpload offlineDataUpload = new OfflineDataUpload { externalUploadId = externalUploadId, offlineDataList = new OfflineData[] { offlineData1, offlineData2 }, // Set the type and metadata of this upload. uploadType = uploadType }; StoreSalesUploadCommonMetadata storeSalesMetaData = null; switch (uploadType) { case OfflineDataUploadType.STORE_SALES_UPLOAD_FIRST_PARTY: storeSalesMetaData = new FirstPartyUploadMetadata() { loyaltyRate = 1, transactionUploadRate = 1 }; break; case OfflineDataUploadType.STORE_SALES_UPLOAD_THIRD_PARTY: storeSalesMetaData = new ThirdPartyUploadMetadata() { loyaltyRate = 1.0, transactionUploadRate = 1.0, advertiserUploadTime = advertiserUploadTime, validTransactionRate = 1.0, partnerMatchRate = 1.0, partnerUploadRate = 1.0, bridgeMapVersionId = bridgeMapVersionId, partnerId = partnerId }; break; } UploadMetadata uploadMetadata = new UploadMetadata { Item = storeSalesMetaData }; offlineDataUpload.uploadMetadata = uploadMetadata; // Create an offline data upload operation. OfflineDataUploadOperation offlineDataUploadOperation = new OfflineDataUploadOperation { @operator = Operator.ADD, operand = offlineDataUpload }; // Keep the operations in an array, so it may be reused later for error processing. List<OfflineDataUploadOperation> operations = new List<OfflineDataUploadOperation>(); operations.Add(offlineDataUploadOperation); try { // Upload offline data to the server. OfflineDataUploadReturnValue result = offlineDataUploadService.mutate(operations.ToArray()); offlineDataUpload = result.value[0]; // Print the upload ID and status. Console.WriteLine( "Uploaded offline data with external upload ID {0}, " + "and upload status {1}.", offlineDataUpload.externalUploadId, offlineDataUpload.uploadStatus); // Print any partial failure errors from the response. if (result.partialFailureErrors != null) { foreach (ApiError apiError in result.partialFailureErrors) { // Get the index of the failed operation from the error's field path // elements. int operationIndex = apiError.GetOperationIndex(); if (operationIndex != -1) { OfflineDataUpload failedOfflineDataUpload = operations[operationIndex].operand; // Get the index of the entry in the offline data list from the // error's field path elements. int offlineDataListIndex = apiError.GetFieldPathIndex("offlineDataList"); Console.WriteLine( "Offline data list entry {0} in operation {1} with external " + "upload ID {2} and type '{3}' has triggered a failure for " + "the following reason: '{4}'.", offlineDataListIndex, operationIndex, failedOfflineDataUpload.externalUploadId, failedOfflineDataUpload.uploadType, apiError.errorString); } else { Console.WriteLine( "A failure has occurred for the following reason: {0}", apiError.errorString); } } } } catch (Exception e) { throw new System.ApplicationException("Failed upload offline data conversions.", e); } } } /// <summary> /// Creates the offline data row from the specified transaction time, transaction micro /// amount, transaction currency, conversion name and user identifier list. /// </summary> /// <param name="transactionTime">The transaction time.</param> /// <param name="transactionMicroAmount">The transaction micro amount.</param> /// <param name="transactionCurrency">The transaction currency.</param> /// <param name="conversionName">Name of the conversion.</param> /// <param name="userIdentifierList">The user identifier list.</param> /// <returns>The offline data row.</returns> private OfflineData CreateOfflineDataRow(DateTime transactionTime, long transactionMicroAmount, string transactionCurrency, string conversionName, UserIdentifier[] userIdentifierList) { StoreSalesTransaction storeSalesTransaction = new StoreSalesTransaction { // For times use the format yyyyMMdd HHmmss [tz]. // For details, see // https://developers.google.com/adwords/api/docs/appendix/codes-formats#date-and-time-formats transactionTime = transactionTime.ToString("yyyyMMdd HHmmss"), conversionName = conversionName, userIdentifiers = userIdentifierList }; Money money = new Money { microAmount = transactionMicroAmount }; RemarketingMoneyWithCurrency moneyWithCurrency = new RemarketingMoneyWithCurrency { money = money, currencyCode = transactionCurrency }; storeSalesTransaction.transactionAmount = moneyWithCurrency; OfflineData offlineData = new OfflineData { Item = storeSalesTransaction }; return offlineData; } /// <summary> /// Hash a string value using SHA-256 hashing algorithm. /// </summary> /// <param name="digest">Provides the algorithm for SHA-256.</param> /// <param name="value">The string value (e.g. an email address) to hash.</param> /// <returns>The hashed value.</returns> private static string ToSha256String(SHA256 digest, string value) { byte[] digestBytes = digest.ComputeHash(Encoding.UTF8.GetBytes(value)); // Convert the byte array into an unhyphenated hexadecimal string. return BitConverter.ToString(digestBytes).Replace("-", string.Empty); } /// <summary> /// Creates the user identifier. /// </summary> /// <param name="type">The user identifier type.</param> /// <param name="value">The user identifier value.</param> /// <returns></returns> private UserIdentifier CreateUserIdentifier(OfflineDataUploadUserIdentifierType type, string value) { // If the user identifier type is a hashed type, also call hash function // on the value. if (type.ToString().StartsWith("HASHED_")) { value = ToSha256String(digest, ToNormalizedValue(value)); } UserIdentifier userIdentifier = new UserIdentifier { userIdentifierType = type, value = value }; return userIdentifier; } /// <summary> /// Removes leading and trailing whitespace and converts all characters to /// lower case. /// </summary> /// <param name="value">The value to normalize.</param> /// <returns>The normalized value.</returns> private static string ToNormalizedValue(string value) { return value.Trim().ToLower(); } } }