Remarketing Samples

The code samples below provide examples of common remarketing functions using the AdWords API. Client Library.

Add audience

#!/usr/bin/env python
#
# Copyright 2016 Google Inc. All Rights Reserved.
#
# 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.

"""This example adds a remarketing user list (a.k.a. audience).

The LoadFromStorage method is pulling credentials and properties from a
"googleads.yaml" file. By default, it looks for this file in your home
directory. For more information, see the "Caching authentication information"
section of our README.

"""


import uuid
from googleads import adwords


def main(client):
  # Initialize appropriate service.
  user_list_service = client.GetService(
      'AdwordsUserListService', version='v201710')
  conversion_tracker_service = client.GetService(
      'ConversionTrackerService', version='v201710')

  # Construct operations and add a user list.
  operations = [
      {
          'operator': 'ADD',
          'operand': {
              'xsi_type': 'BasicUserList',
              'name': 'Mars cruise customers #%s' % uuid.uuid4(),
              'description': 'A list of mars cruise customers in the last year',
              'membershipLifeSpan': '365',
              'conversionTypes': [
                  {
                      'name': ('Mars cruise customers #%s'
                               % uuid.uuid4())
                  }
              ],
              # Optional field.
              'status': 'OPEN',
          }
      }
  ]
  result = user_list_service.mutate(operations)

  # Display results.
  if 'value' in result:
    conversion_ids = []
    for user_list in result['value']:
      if user_list['conversionTypes']:
        for conversion_type in user_list['conversionTypes']:
          conversion_ids.append(conversion_type['id'])

    selector = {
        'fields': ['Name', 'Status', 'Category'],
        'predicates': [{
            'field': 'Id',
            'operator': 'IN',
            'values': conversion_ids
        }],
        'ordering': [{
            'field': 'Name',
            'sortOrder': 'ASCENDING'
        }]
    }

    pages = conversion_tracker_service.get(selector)
    conversions_map = {}
    if pages['entries']:
      for conversion_tracker in pages['entries']:
        conversions_map[conversion_tracker['id']] = conversion_tracker

    for user_list in result['value']:
      print ('User list with name "%s" and ID "%s" was added.'
             % (user_list['name'], user_list['id']))
      if user_list['conversionTypes']:
        for conversion_type in user_list['conversionTypes']:
          conversion_tracker = conversions_map[conversion_type['id']]
          print ('Conversion type code snippet associated to the list:\n%s\n'
                 % conversion_tracker['snippet'])
  else:
    print 'No user lists were added.'


if __name__ == '__main__':
  # Initialize client object.
  adwords_client = adwords.AdWordsClient.LoadFromStorage()

  main(adwords_client)

Add conversion trackers

#!/usr/bin/env python
#
# Copyright 2016 Google Inc. All Rights Reserved.
#
# 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.

"""This example adds an AdWords conversion.

The LoadFromStorage method is pulling credentials and properties from a
"googleads.yaml" file. By default, it looks for this file in your home
directory. For more information, see the "Caching authentication information"
section of our README.

"""


import uuid
from googleads import adwords


def main(client):
  # Initialize appropriate service.
  conversion_tracker_service = client.GetService(
      'ConversionTrackerService', version='v201710')

  # Construct operations and add conversion_tracker.
  operations = [
      {
          'operator': 'ADD',
          'operand': {
              'xsi_type': 'AdWordsConversionTracker',
              'name': 'Mars cruise customers #%s' % uuid.uuid4(),
              'category': 'DEFAULT',
              'textFormat': 'HIDDEN',
              # Optional fields.
              'status': 'ENABLED',
              'viewthroughLookbackWindow': '15',
              'conversionPageLanguage': 'en',
              'backgroundColor': '#0000FF',
              'defaultRevenueValue': '23.41',
              'alwaysUseDefaultRevenueValue': 'true'
          }
      }
  ]
  conversion_trackers = conversion_tracker_service.mutate(operations)

  # Display results.
  for conversion_tracker in conversion_trackers['value']:
    print ('Conversion tracker with id "%s", name "%s", status "%s" '
           'and category "%s" and snippet \n"%s"\n was added.\n' %
           (conversion_tracker['id'], conversion_tracker['name'],
            conversion_tracker['status'], conversion_tracker['category'],
            conversion_tracker['snippet']))


if __name__ == '__main__':
  # Initialize client object.
  adwords_client = adwords.AdWordsClient.LoadFromStorage()

  main(adwords_client)

Add CRM-based user list

#!/usr/bin/env python
#
# Copyright 2016 Google Inc. All Rights Reserved.
#
# 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.


"""Adds a user list and populates it with hashed email addresses.

Note: It may take 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.
"""


import hashlib
import uuid

# Import appropriate modules from the client library.
from googleads import adwords


def main(client):
  # Initialize appropriate services.
  user_list_service = client.GetService('AdwordsUserListService', 'v201710')

  user_list = {
      'xsi_type': 'CrmBasedUserList',
      'name': 'Customer relationship management list #%d' % uuid.uuid4(),
      'description': 'A list of customers that originated from email addresses',
      # Maximum lifespan is 180 days.
      'membershipLifeSpan': 180
  }

  # Create an operation to add the user list.
  operations = [{
      'operator': 'ADD',
      'operand': user_list
  }]

  result = user_list_service.mutate(operations)
  user_list_id = result['value'][0]['id']

  emails = ['customer1@example.com', 'customer2@example.com',
            ' Customer3@example.com ']
  members = [{'hashedEmail': NormalizeAndSHA256(email)} for email in emails]

  # Optional: AddressInfo is only accessible to whitelisted customers.
  # If you are not on the whitelist, you should leave this code commented out.
  # members.append({
  #     'addressInfo': {
  #         'hashedFirstName': NormalizeAndSHA256('John'),
  #         'hashedLastName': NormalizeAndSHA256('Doe'),
  #         'countryCode': 'US',
  #         'zipCode': '10001'
  #     }
  # })

  mutate_members_operation = {
      'operand': {
          'userListId': user_list_id,
          'membersList': members
      },
      'operator': 'ADD'
  }

  response = user_list_service.mutateMembers([mutate_members_operation])

  if 'userLists' in response:
    for user_list in response['userLists']:
      print ('User list with name "%s" and ID "%d" was added.'
             % (user_list['name'], user_list['id']))


def NormalizeAndSHA256(s):
  """Normalizes (lowercase, remove whitespace) and hashes a string with SHA-256.

  Args:
    s: The string to perform this operation on.

  Returns:
    A normalized and SHA-256 hashed string.
  """
  return hashlib.sha256(s.strip().lower()).hexdigest()


if __name__ == '__main__':
  # Initialize client object.
  adwords_client = adwords.AdWordsClient.LoadFromStorage()
  main(adwords_client)

Add rule-based user list

#!/usr/bin/env python
#
# Copyright 2016 Google Inc. All Rights Reserved.
#
# 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.

"""This example adds two rule-based remarketing user lists.

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.

The LoadFromStorage method is pulling credentials and properties from a
"googleads.yaml" file. By default, it looks for this file in your home
directory. For more information, see the "Caching authentication information"
section of our README.

"""


import calendar
from datetime import date
from datetime import datetime
from datetime import timedelta
from googleads import adwords


def main(client):
  # Initialize appropriate service.
  adwords_user_list_service = client.GetService(
      'AdwordsUserListService', version='v201710')

  # First rule item group - users who visited the checkout page and had more
  # than one item in their shopping cart.
  checkout_rule_item = {
      'StringRuleItem': {
          'key': {
              'name': 'ecomm_pagetype'
          },
          'op': 'EQUALS',
          'value': 'checkout'
      }
  }

  cart_size_rule_item = {
      'NumberRuleItem': {
          'key': {
              'name': 'cartsize'
          },
          'op': 'GREATER_THAN',
          'value': '1.0'
      }
  }

  # Combine the two rule items into a RuleItemGroup so AdWords will logically
  # AND the rules together.
  checkout_multiple_item_group = {
      'items': [checkout_rule_item, cart_size_rule_item]
  }

  # Second rule item group - users who checked out within the next 3 months.
  today = date.today()
  start_date_rule_item = {
      'DateRuleItem': {
          'key': {
              'name': 'checkoutdate'
          },
          'op': 'AFTER',
          'value': today.strftime('%Y%m%d')
      }
  }

  three_months_later = AddMonths(today, 3)

  three_months_later_rule_item = {
      'DateRuleItem': {
          'key': {
              'name': 'checkoutdate'
          },
          'op': 'BEFORE',
          'value': three_months_later.strftime('%Y%m%d')
      }
  }

  # Combine the date rule items into a RuleItemGroup
  checked_out_date_range_item_group = {
      'items': [start_date_rule_item, three_months_later_rule_item]
  }

  # Combine the rule item groups into a Rule so AdWords knows how to apply the
  # rules.
  rule = {
      'groups': [
          checkout_multiple_item_group,
          checked_out_date_range_item_group
      ],
      # 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': 'DNF'
  }

  # Third and fourth rule item groups.
  # Visitors of a page who visited another page.
  site1_rule_item = {
      'StringRuleItem': {
          'key': {'name': 'url__'},
          'op': 'EQUALS',
          'value': 'example.com/example1'
      }
  }
  site2_rule_item = {
      'StringRuleItem': {
          'key': {'name': 'url__'},
          'op': 'EQUALS',
          'value': 'example.com/example2'
      }
  }

  # Create two rules to show that a visitor browsed two sites.
  user_visited_site1_rule = {
      'groups': [{
          'items': [site1_rule_item]
      }]
  }

  user_visited_site2_rule = {
      'groups': [{
          'items': [site2_rule_item]
      }]
  }

  # Create the user list with no restrictions on site visit date.
  expression_user_list = {
      'xsi_type': 'ExpressionRuleUserList',
      'name': 'Expression-based user list created at %s'
              % datetime.today().strftime('%Y%m%d %H:%M:%S'),
      'description': 'Users who checked out in three month window OR visited'
                     ' the checkout page with more than one item in their'
                     ' cart.',
      'rule': rule,
      # Optional: Set the populationStatus to REQUESTED to include past users in
      # the user list.
      'prepopulationStatus': 'REQUESTED'
  }

  # Create the user list restricted to users who visit your site within the next
  # six months.
  end_date = AddMonths(today, 6)

  date_user_list = {
      'xsi_type': 'DateSpecificRuleUserList',
      'name': 'Date rule user list created at %s'
              % datetime.today().strftime('%Y%m%d %H:%M:%S'),
      'description': 'Users who visited the site between %s and %s and checked'
                     ' out in three month window OR visited the checkout page'
                     ' with more than one item in their cart.'
                     % (today.strftime('%Y%m%d'), end_date.strftime('%Y%m%d')),
      'rule': rule,
      'startDate': today.strftime('%Y%m%d'),
      'endDate': end_date.strftime('%Y%m%d')
  }

  # Create the user list for "Visitors of a page who did visit another page".
  # To create a user list for "Visitors of a page who did not visit another
  # page", change the ruleOperator from AND to AND_NOT.
  combined_user_list = {
      'xsi_type': 'CombinedRuleUserList',
      'name': 'Combined rule user lst create at ${creation_time}',
      'description': 'Users who visited two sites.',
      'leftOperand': user_visited_site1_rule,
      'rightOperand': user_visited_site2_rule,
      'ruleOperator': 'AND'
  }

  # Create operations to add the user lists.
  operations = [
      {
          'operand': user_list,
          'operator': 'ADD',
      } for user_list in [expression_user_list, date_user_list,
                          combined_user_list]
  ]

  # Submit the operations.
  user_lists = adwords_user_list_service.mutate(operations)

  # Display results.
  for user_list in user_lists['value']:
    print (('User list added with ID %d, name "%s", status "%s", list type'
            ' "%s", accountUserListStatus "%s", description "%s".') %
           (user_list['id'], user_list['name'],
            user_list['status'], user_list['listType'],
            user_list['accountUserListStatus'], user_list['description']))


def AddMonths(start_date, months):
  """A simple convenience utility for adding months to a given start date.

  This increments the months by adding the number of days in the current month
  to the current month, for each month.

  Args:
    start_date: date The date months are being added to.
    months: int The number of months to add.

  Returns:
    A date equal to the start date incremented by the given number of months.
  """
  current_date = start_date
  i = 0
  while i < months:
    month_days = calendar.monthrange(current_date.year, current_date.month)[1]
    current_date += timedelta(days=month_days)
    i += 1
  return current_date


if __name__ == '__main__':
  # Initialize client object.
  adwords_client = adwords.AdWordsClient.LoadFromStorage()

  main(adwords_client)

Upload offline conversions

#!/usr/bin/env python
#
# Copyright 2016 Google Inc. All Rights Reserved.
#
# 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.

"""Imports offline conversion values for specific clicks into your account.

To get the Google Click ID for a click, run a CLICK_PERFORMANCE_REPORT. To set
up a conversion tracker, run the add_conversion_trackers.py example.

The LoadFromStorage method is pulling credentials and properties from a
"googleads.yaml" file. By default, it looks for this file in your home
directory. For more information, see the "Caching authentication information"
section of our README.

"""

from googleads import adwords

# Name of the conversion tracker to upload to.
CONVERSION_NAME = 'INSERT_CONVERSION_NAME_HERE'
# Your click ID must be less than 30 days old.
CLICK_ID = 'INSERT_GOOGLE_CLICK_ID_HERE'
# The conversion time must be more recent than the time of the click.
CONVERSION_TIME = 'INSERT_CONVERSION_TIME_HERE'
CONVERSION_VALUE = 'INSERT_CONVERSION_VALUE_HERE'


def main(client, conversion_name, click_id, conversion_time, conversion_value):
  # Initialize appropriate services.
  offline_conversion_feed_service = client.GetService(
      'OfflineConversionFeedService', version='v201710')

  # 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.
  feed = {
      'conversionName': conversion_name,
      'conversionTime': conversion_time,
      'conversionValue': conversion_value,
      'googleClickId': click_id,
      # 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. To learn more about
      # importing externally attributed conversins, see:
      # https://developers.google.com/adwords/api/docs/guides/conversion-tracking#importing_externally_attributed_conversions
      # 'externalAttributionCredit': 0.3,
      # 'externalAttributionModel': 'Linear'
  }

  offline_conversion_operation = {
      'operator': 'ADD',
      'operand': feed
  }

  offline_conversion_response = offline_conversion_feed_service.mutate(
      [offline_conversion_operation])
  new_feed = offline_conversion_response['value']

  print ('Uploaded offline conversion value of "%s" for Google Click ID '
         '"%s" to "%s".' % (new_feed['conversionValue'],
                            new_feed['googleClickId'],
                            new_feed['conversionName']))


if __name__ == '__main__':
  # Initialize client object.
  adwords_client = adwords.AdWordsClient.LoadFromStorage()

  main(adwords_client, CONVERSION_NAME, CLICK_ID, CONVERSION_TIME,
       CONVERSION_VALUE)

Upload offline call conversions

#!/usr/bin/env python
#
# Copyright 2016 Google Inc. All Rights Reserved.
#
# 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.

"""Imports offline conversion values for calls related to ads in your account.

To set up a conversion tracker, run the add_conversion_trackers.py example.

The LoadFromStorage method is pulling credentials and properties from a
"googleads.yaml" file. By default, it looks for this file in your home
directory. For more information, see the "Caching authentication information"
section of our README.

"""

from googleads import adwords


CALLER_ID = 'INSERT_CALLER_ID_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
CALL_START_TIME = 'INSERT_CALL_START_TIME'
CONVERSION_NAME = 'INSERT_CONVERSION_NAME_HERE'  # Name of conversion tracker.
CONVERSION_TIME = 'INSERT_CONVERSION_TIME_HERE'
CONVERSION_VALUE = 'INSERT_CONVERSION_VALUE_HERE'


def main(client, caller_id, call_start_time, conversion_name, conversion_time,
         conversion_value):
  # Initialize appropriate services.
  occ_feed_service = client.GetService(
      'OfflineCallConversionFeedService', version='v201710')

  # 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.
  feed = {
      'callerId': caller_id,
      'callStartTime': call_start_time,
      'conversionName': conversion_name,
      'conversionTime': conversion_time,
      'conversionValue': conversion_value,
  }

  occ_operations = [{'operator': 'ADD', 'operand': feed}]

  occ_response = occ_feed_service.mutate(occ_operations)
  values = occ_response['value']

  if values:
    for occ_feed in values:
      print ('Uploaded offline call conversion value of "%s" for caller ID '
             '"%s".\n' % (occ_feed['conversionName'], occ_feed['callerId']))
  else:
    print 'No offline call conversions were added.'


if __name__ == '__main__':
  # Initialize client object.
  adwords_client = adwords.AdWordsClient.LoadFromStorage()

  main(adwords_client, CALLER_ID, CALL_START_TIME, CONVERSION_NAME,
       CONVERSION_TIME, CONVERSION_VALUE)

Upload offline data


#!/usr/bin/python
#
# Copyright 2017 Google Inc. All Rights Reserved.
#
# 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.

"""This example shows how to upload offline data for store sales transactions.

The LoadFromStorage method is pulling credentials and properties from a
"googleads.yaml" file. By default, it looks for this file in your home
directory. For more information, see the "Caching authentication information"
section of our README.

"""

import datetime
import hashlib

import google3
from googleads import adwords
import pytz


_DT_FORMAT = '%Y%m%d %H%M%S'
# User identifier types whose values must be hashed.
_HASHED_IDENTIFIER_TYPES = ('HASHED_EMAIL', 'HASHED_FIRST_NAME',
                            'HASHED_LAST_NAME', 'HASHED_PHONE')
# The timezone to be used in this example. For valid timezone IDs, see:
# https://developers.google.com/adwords/api/docs/appendix/codes-formats#timezone-ids
_TIMEZONE = pytz.timezone('America/New_York')
# Name of the conversion tracker to upload to.
CONVERSION_NAME = 'INSERT_CONVERSION_NAME_HERE'
# Insert email addresses below for creating user identifiers.
EMAIL_ADDRESSES = ['EMAIL_ADDRESS_1', 'EMAIL_ADDRESS_2']
# The external upload ID can be any number that you use to keep track of your
# uploads.
EXTERNAL_UPLOAD_ID = 'INSERT_EXTERNAL_UPLOAD_ID'


def main(client, conversion_name, external_upload_id, email_addresses):
  # Initialize appropriate services.
  offline_data_upload_service = client.GetService(
      'OfflineDataUploadService', version='v201710')

  # Create the first offline data for upload.
  # This transaction occurred 7 days ago with an amount of $200 USD.
  transaction_time_1 = (datetime.datetime.now(tz=_TIMEZONE) -
                        datetime.timedelta(days=7))
  offline_data_1 = {
      'StoreSalesTransaction': {
          'userIdentifiers': [
              _CreateUserIdentifier(identifier_type='HASHED_EMAIL',
                                    value=email_addresses[0]),
              _CreateUserIdentifier(identifier_type='STATE', value='New York')
          ],
          'transactionTime': _GetFormattedDateTime(transaction_time_1),
          'transactionAmount': {
              'currencyCode': 'USD',
              'money': {
                  'microAmount': 200000000
              }
          },
          'conversionName': conversion_name
      }
  }

  # Create the second offline data for upload.
  # This transaction occurred 14 days ago with amount of 450 EUR.
  transaction_time_2 = (datetime.datetime.now(tz=_TIMEZONE) -
                        datetime.timedelta(days=14))
  offline_data_2 = {
      'StoreSalesTransaction': {
          'userIdentifiers': [
              _CreateUserIdentifier(identifier_type='HASHED_EMAIL',
                                    value=email_addresses[1]),
              _CreateUserIdentifier(identifier_type='STATE', value='California')
          ],
          'transactionTime': _GetFormattedDateTime(transaction_time_2),
          'transactionAmount': {
              'currencyCode': 'EUR',
              'money': {
                  'microAmount': 450000000
              }
          },
          'conversionName': conversion_name
      }
  }

  # Create offline data upload
  offline_data_upload = {
      'externalUploadId': external_upload_id,
      'offlineDataList': [offline_data_1, offline_data_2],
      # Optional: You can set the type of this upload.
      # 'uploadType': 'STORE_SALES_UPLOAD_FIRST_PARTY'
  }

  # Create an offline data upload operation.
  operations = [{
      'operator': 'ADD',
      'operand': offline_data_upload
  }]

  # Upload offline data on the server and print the result.
  result = offline_data_upload_service.mutate(operations)
  offline_data_upload = result['value'][0]

  print ('Uploaded offline data with external upload ID "%d" and upload status '
         '"%s".' % (offline_data_upload['externalUploadId'],
                    offline_data_upload['uploadStatus']))

  # Print any partial data errors from the response. The order of the partial
  # data errors list is the same as the uploaded offline data list in the
  # request.
  for i, partial_data_error in enumerate(
      offline_data_upload['partialDataErrors']):
    # If a partial error occurred for this offline data, print the error. Note
    # that non-errors for a given offline data would be set to None.
    if partial_data_error:
      print ('Found a partial error for offline data #%d with error string: %s'
             % (i, partial_data_error['errorString']))


def _CreateUserIdentifier(identifier_type=None, value=None):
  """Creates a user identifier from the specified type and value.

  Args:
    identifier_type: a str specifying the type of user identifier.
    value: a str value of the identifier; to be hashed using SHA-256 if needed.

  Returns:
    A dict specifying a user identifier, with a value hashed using SHA-256 if
      needed.
  """
  if identifier_type in _HASHED_IDENTIFIER_TYPES:
    # If the user identifier type is a hashed type, normalize and hash the
    # value.
    value = hashlib.sha256(value.strip().lower()).hexdigest()

  user_identifier = {
      'userIdentifierType': identifier_type,
      'value': value
  }

  return user_identifier


def _GetFormattedDateTime(dt):
  """Formats the given datetime and timezone for use with AdWords.

  Args:
    dt: a datetime instance.

  Returns:
    A str representation of the datetime in the correct format for AdWords.
  """
  return '%s %s' % (datetime.datetime.strftime(dt, _DT_FORMAT), _TIMEZONE.zone)


if __name__ == '__main__':
  # Initialize client object.
  adwords_client = adwords.AdWordsClient.LoadFromStorage()

  main(adwords_client, CONVERSION_NAME, EXTERNAL_UPLOAD_ID, EMAIL_ADDRESSES)

Send feedback about...

AdWords API
AdWords API
Need help? Visit our support page.