您可以使用 Google Ads API 管理 Google Ads 中的在线点击转化。在线点击转化有助于您跟踪促成在线销售(例如通过网站)的广告。
线上转化通过 Google 代码进行跟踪,但您可以使用 Google Ads API 对其进行调整或增强。
如果您已设置 Google 代码,并想调整在线转化,请参阅转化调整页面。
如果您已设置 Google 代码,并希望使用用户提供的数据来增强在线转化跟踪效果(也称为增强型网站转化),请继续阅读。
增强型网站转化
以下部分介绍了如何增强在线点击转化,也称为增强型网站转化。
增强型网站转化需要设置一个代码,以便在用户转化时自动将点击标识符(例如 GCLID)和订单 ID 发送到 Google Ads。您可以通过 Google 跟踪代码管理器、Google 代码或 Google Ads API 设置增强型转化。
使用 Google Ads API 的优势在于,您可以在转化事件发生后的 24 小时内发送第一方转化数据,而不是在同一时间发送。这样一来,您就可以从各种来源(例如客户数据库或 CRM 系统)找到第一方数据。
增强型网站转化的运作方式
Google Ads API 中的增强型网站转化是对以下流程中第 3 步的补充。
该代码不会在用户转化时发送经过哈希处理的用户信息,而只会发送 GCLID 和订单 ID;您可以在稍后通过导入订单 ID 和经过哈希处理的数据来发送经过哈希处理的用户信息。如需详细了解增强型网站转化,请访问我们的帮助中心。
前提条件
您必须先接受客户数据条款,然后才能使用增强型网站转化。您可以向 Google Ads 转化客户发出以下查询,以验证客户数据条款是否已被接受:
defnormalize_and_hash_email_address(email_address):"""Returns the result of normalizing and hashing an email address. For this use case, Google Ads requires removal of any '.' characters preceding "gmail.com" or "googlemail.com" Args: email_address: An email address to normalize. Returns: A normalized (lowercase, removed whitespace) and SHA-265 hashed string. """normalized_email=email_address.strip().lower()email_parts=normalized_email.split("@")# Check that there are at least two segmentsiflen(email_parts) > 1:# Checks whether the domain of the email address is either "gmail.com"# or "googlemail.com". If this regex does not match then this statement# will evaluate to None.ifre.match(r"^(gmail|googlemail)\.com$",email_parts[1]):# Removes any '.' characters from the portion of the email address# before the domain if the domain is gmail.com or googlemail.com.email_parts[0]=email_parts[0].replace(".","")normalized_email="@".join(email_parts)returnnormalize_and_hash(normalized_email)defnormalize_and_hash(s):"""Normalizes and hashes a string with SHA-256. Private customer data must be hashed during upload, as described at: https://support.google.com/google-ads/answer/9888656 Args: s: The string to perform this operation on. Returns: A normalized (lowercase, removed whitespace) and SHA-256 hashed string. """returnhashlib.sha256(s.strip().lower().encode()).hexdigest()
# Returns the result of normalizing and then hashing the string using the# provided digest. Private customer data must be hashed during upload, as# described at https://support.google.com/google-ads/answer/9888656.defnormalize_and_hash(str)# Remove leading and trailing whitespace and ensure all letters are lowercase# before hasing.Digest::SHA256.hexdigest(str.strip.downcase)end# Returns the result of normalizing and hashing an email address. For this use# case, Google Ads requires removal of any '.' characters preceding 'gmail.com'# or 'googlemail.com'.defnormalize_and_hash_email(email)email_parts=email.downcase.split("@")# Removes any '.' characters from the portion of the email address before the# domain if the domain is gmail.com or googlemail.com.ifemail_parts.last=~/^(gmail|googlemail)\.com\s*/email_parts[0]=email_parts[0].gsub('.','')endnormalize_and_hash(email_parts.join('@'))end
subnormalize_and_hash{my$value=shift;my$trim_intermediate_spaces=shift;if($trim_intermediate_spaces){$value=~s/\s+//g;}else{$value=~s/^\s+|\s+$//g;}returnsha256_hex(lc$value);}# Returns the result of normalizing and hashing an email address. For this use# case, Google Ads requires removal of any '.' characters preceding 'gmail.com'# or 'googlemail.com'.subnormalize_and_hash_email_address{my$email_address=shift;my$normalized_email=lc$email_address;my@email_parts=split('@',$normalized_email);if(scalar@email_parts > 1 && $email_parts[1]=~ /^(gmail|googlemail)\.com\s*/){# Remove any '.' characters from the portion of the email address before the# domain if the domain is 'gmail.com' or 'googlemail.com'.$email_parts[0]=~s/\.//g;$normalized_email=sprintf'%s@%s',$email_parts[0],$email_parts[1];}returnnormalize_and_hash($normalized_email,1);}
# Extracts user email, phone, and address info from the raw data, normalizes# and hashes it, then wraps it in UserIdentifier objects. Creates a separate# UserIdentifier object for each. The data in this example is hardcoded, but# in your application you might read the raw data from an input file.# IMPORTANT: Since the identifier attribute of UserIdentifier# (https://developers.google.com/google-ads/api/reference/rpc/latest/UserIdentifier)# is a oneof# (https://protobuf.dev/programming-guides/proto3/#oneof-features), you must# set only ONE of hashed_email, hashed_phone_number, mobile_id,# third_party_user_id, or address_info. Setting more than one of these# attributes on the same UserIdentifier will clear all the other members of# the oneof. For example, the following code is INCORRECT and will result in# a UserIdentifier with ONLY a hashed_phone_number:## incorrectly_populated_user_identifier = client.get_type("UserIdentifier")# incorrectly_populated_user_identifier.hashed_email = "...""# incorrectly_populated_user_identifier.hashed_phone_number = "...""raw_record={# Email address that includes a period (.) before the Gmail domain."email":"alex.2@example.com",# Address that includes all four required elements: first name, last# name, country code, and postal code."first_name":"Alex","last_name":"Quinn","country_code":"US","postal_code":"94045",# Phone number to be converted to E.164 format, with a leading '+' as# required."phone":"+1 800 5550102",# This example lets you input conversion details as arguments, but in# reality you might store this data alongside other user data, so we# include it in this sample user record."order_id":order_id,"conversion_action_id":conversion_action_id,"conversion_date_time":conversion_date_time,"currency_code":"USD","user_agent":user_agent,}# Constructs the enhancement adjustment.conversion_adjustment=client.get_type("ConversionAdjustment")conversion_adjustment.adjustment_type=(client.enums.ConversionAdjustmentTypeEnum.ENHANCEMENT)# Creates a user identifier using the hashed email address, using the# normalize and hash method specifically for email addresses.email_identifier=client.get_type("UserIdentifier")# Optional: Specifies the user identifier source.email_identifier.user_identifier_source=(client.enums.UserIdentifierSourceEnum.FIRST_PARTY)# Uses the normalize and hash method specifically for email addresses.email_identifier.hashed_email=normalize_and_hash_email_address(raw_record["email"])# Adds the email identifier to the conversion adjustment.conversion_adjustment.user_identifiers.append(email_identifier)# Checks if the record has a phone number, and if so, adds a UserIdentifier# for it.ifraw_record.get("phone")isnotNone:phone_identifier=client.get_type("UserIdentifier")phone_identifier.hashed_phone_number=normalize_and_hash(raw_record["phone"])# Adds the phone identifier to the conversion adjustment.conversion_adjustment.user_identifiers.append(phone_identifier)# Checks if the record has all the required mailing address elements, and if# so, adds a UserIdentifier for the mailing address.ifraw_record.get("first_name")isnotNone:# Checks if the record contains all the other required elements of a# mailing address.required_keys=["last_name","country_code","postal_code"]# Builds a new list of the required keys that are missing from# raw_record.missing_keys=[keyforkeyinrequired_keysifkeynotinraw_record.keys()]iflen(missing_keys) > 0:print("Skipping addition of mailing address information because the"f"following required keys are missing: {missing_keys}")else:# Creates a user identifier using sample values for the user address,# hashing where required.address_identifier=client.get_type("UserIdentifier")address_info=address_identifier.address_infoaddress_info.hashed_first_name=normalize_and_hash(raw_record["first_name"])address_info.hashed_last_name=normalize_and_hash(raw_record["last_name"])address_info.country_code=raw_record["country_code"]address_info.postal_code=raw_record["postal_code"]# Adds the address identifier to the conversion adjustment.conversion_adjustment.user_identifiers.append(address_identifier)
# Extracts user email, phone, and address info from the raw data, normalizes# and hashes it, then wraps it in UserIdentifier objects. Creates a separate# UserIdentifier object for each. The data in this example is hardcoded, but# in your application you might read the raw data from an input file.# IMPORTANT: Since the identifier attribute of UserIdentifier# (https://developers.google.com/google-ads/api/reference/rpc/latest/UserIdentifier)# is a oneof# (https://protobuf.dev/programming-guides/proto3/#oneof-features), you must# set only ONE of hashed_email, hashed_phone_number, mobile_id,# third_party_user_id, or address_info. Setting more than one of these# attributes on the same UserIdentifier will clear all the other members of# the oneof. For example, the following code is INCORRECT and will result in# a UserIdentifier with ONLY a hashed_phone_number:## incorrectly_populated_user_identifier.hashed_email = "...""# incorrectly_populated_user_identifier.hashed_phone_number = "...""raw_record={# Email address that includes a period (.) before the Gmail domain."email"=>"alex.2@example.com",# Address that includes all four required elements: first name, last# name, country code, and postal code."first_name"=>"Alex","last_name"=>"Quinn","country_code"=>"US","postal_code"=>"94045",# Phone number to be converted to E.164 format, with a leading '+' as# required."phone"=>"+1 800 5550102",# This example lets you input conversion details as arguments, but in# reality you might store this data alongside other user data, so we# include it in this sample user record."order_id"=>order_id,"conversion_action_id"=>conversion_action_id,"conversion_date_time"=>conversion_date_time,"currency_code"=>"USD","user_agent"=>user_agent,}enhancement=client.resource.conversion_adjustmentdo|ca|ca.conversion_action=client.path.conversion_action(customer_id,conversion_action_id)ca.adjustment_type=:ENHANCEMENTca.order_id=order_id# Sets the conversion date and time if provided. Providing this value is# optional but recommended.unlessconversion_date_time.nil?ca.gclid_date_time_pair=client.resource.gclid_date_time_pairdo|pair|pair.conversion_date_time=conversion_date_timeendend# Creates a user identifier using the hashed email address, using the# normalize and hash method specifically for email addresses.ca.user_identifiers << client.resource.user_identifierdo|ui|# Uses the normalize and hash method specifically for email addresses.ui.hashed_email=normalize_and_hash_email(raw_record["email"])# Optional: Specifies the user identifier source.ui.user_identifier_source=:FIRST_PARTYend# Checks if the record has a phone number, and if so, adds a UserIdentifier# for it.unlessraw_record["phone"].nil?ca.user_identifiers << client.resource.user_identifierdo|ui|ui.hashed_phone_number=normalize_and_hash_email(raw_record["phone"])endend# Checks if the record has all the required mailing address elements, and if# so, adds a UserIdentifier for the mailing address.unlessraw_record["first_name"].nil?# Checks if the record contains all the other required elements of a# mailing address.required_keys=["last_name","country_code","postal_code"]# Builds a new list of the required keys that are missing from# raw_record.missing_keys=required_keys-raw_record.keysifmissing_keysputs("Skipping addition of mailing address information because the"\"following required keys are missing: #{missing_keys}")elseca.user_identifiers << client.resource.user_identifierdo|ui|ui.address_info=client.resource.offline_user_address_infodo|info|# Certain fields must be hashed using SHA256 in order to handle# identifiers in a privacy-safe way, as described at# https://support.google.com/google-ads/answer/9888656.info.hashed_first_name=normalize_and_hash(raw_record["first_name"])info.hashed_last_name=normalize_and_hash(raw_record["last_name"])info.postal_code=normalize_and_hash(raw_record["country_code"])info.country_code=normalize_and_hash(raw_record["postal_code"])endendendend
# Construct the enhancement adjustment.my$enhancement=Google::Ads::GoogleAds::V22::Services::ConversionAdjustmentUploadService::ConversionAdjustment->new({adjustmentType=>ENHANCEMENT});# Extract user email, phone, and address info from the raw data,# normalize and hash it, then wrap it in UserIdentifier objects.# Create a separate UserIdentifier object for each.# The data in this example is hardcoded, but in your application# you might read the raw data from an input file.## IMPORTANT: Since the identifier attribute of UserIdentifier# (https://developers.google.com/google-ads/api/reference/rpc/latest/UserIdentifier)# is a oneof# (https://protobuf.dev/programming-guides/proto3/#oneof-features), you must set# only ONE of hashed_email, hashed_phone_number, mobile_id, third_party_user_id,# or address-info. Setting more than one of these attributes on the same UserIdentifier# will clear all the other members of the oneof. For example, the following code is# INCORRECT and will result in a UserIdentifier with ONLY a hashed_phone_number:## my $incorrect_user_identifier = Google::Ads::GoogleAds::V22::Common::UserIdentifier->new({# hashedEmail => '...',# hashedPhoneNumber => '...',# });my$raw_record={# Email address that includes a period (.) before the Gmail domain.email=>'alex.2@example.com',# Address that includes all four required elements: first name, last# name, country code, and postal code.firstName=>'Alex',lastName=>'Quinn',countryCode=>'US',postalCode=>'94045',# Phone number to be converted to E.164 format, with a leading '+' as# required.phone=>'+1 800 5550102',# This example lets you input conversion details as arguments,# but in reality you might store this data alongside other user data,# so we include it in this sample user record.orderId=>$order_id,conversionActionId=>$conversion_action_id,conversionDateTime=>$conversion_date_time,currencyCode=>"USD",userAgent=>$user_agent,};my$user_identifiers=[];# Create a user identifier using the hashed email address, using the normalize# and hash method specifically for email addresses.my$hashed_email=normalize_and_hash_email_address($raw_record->{email});push(@$user_identifiers,Google::Ads::GoogleAds::V22::Common::UserIdentifier->new({hashedEmail=>$hashed_email,# Optional: Specify the user identifier source.userIdentifierSource=>FIRST_PARTY}));# Check if the record has a phone number, and if so, add a UserIdentifier for it.if(defined$raw_record->{phone}){# Add the hashed phone number identifier to the list of UserIdentifiers.push(@$user_identifiers,Google::Ads::GoogleAds::V22::Common::UserIdentifier->new({hashedPhoneNumber=>normalize_and_hash($raw_record->{phone},1)}));}# Confirm the record has all the required mailing address elements, and if so, add# a UserIdentifier for the mailing address.if(defined$raw_record->{firstName}){my$required_keys=["lastName","countryCode","postalCode"];my$missing_keys=[];foreachmy$key(@$required_keys){if(!defined$raw_record->{$key}){push(@$missing_keys,$key);}}if(@$missing_keys){print"Skipping addition of mailing address information because the following"."keys are missing: ".join(",",@$missing_keys);}else{push(@$user_identifiers,Google::Ads::GoogleAds::V22::Common::UserIdentifier->new({addressInfo=>
Google::Ads::GoogleAds::V22::Common::OfflineUserAddressInfo->new({# First and last name must be normalized and hashed.hashedFirstName=>normalize_and_hash($raw_record->{firstName}),hashedLastName=>normalize_and_hash($raw_record->{lastName}),# Country code and zip code are sent in plain text.countryCode=>$raw_record->{countryCode},postalCode=>$raw_record->{postalCode},})}));}}# Add the user identifiers to the enhancement adjustment.$enhancement->{userIdentifiers}=$user_identifiers;
conversion_action_service=client.get_service("ConversionActionService")# Sets the conversion action.conversion_adjustment.conversion_action=(conversion_action_service.conversion_action_path(customer_id,raw_record["conversion_action_id"]))# Sets the order ID. Enhancements MUST use order ID instead of GCLID# date/time pair.conversion_adjustment.order_id=order_id# Sets the conversion date and time if provided. Providing this value is# optional but recommended.ifraw_record.get("conversion_date_time"):conversion_adjustment.gclid_date_time_pair.conversion_date_time=(raw_record["conversion_date_time"])# Sets optional fields where a value was providedifraw_record.get("user_agent"):# Sets the user agent. This should match the user agent of the request# that sent the original conversion so the conversion and its# enhancement are either both attributed as same-device or both# attributed as cross-device.conversion_adjustment.user_agent=user_agent
ca.conversion_action=client.path.conversion_action(customer_id,conversion_action_id)ca.adjustment_type=:ENHANCEMENTca.order_id=order_id# Sets the conversion date and time if provided. Providing this value is# optional but recommended.unlessconversion_date_time.nil?ca.gclid_date_time_pair=client.resource.gclid_date_time_pairdo|pair|pair.conversion_date_time=conversion_date_timeendend# Creates a user identifier using the hashed email address, using the# normalize and hash method specifically for email addresses.ca.user_identifiers << client.resource.user_identifierdo|ui|# Uses the normalize and hash method specifically for email addresses.ui.hashed_email=normalize_and_hash_email(raw_record["email"])# Optional: Specifies the user identifier source.ui.user_identifier_source=:FIRST_PARTYend# Checks if the record has a phone number, and if so, adds a UserIdentifier# for it.unlessraw_record["phone"].nil?ca.user_identifiers << client.resource.user_identifierdo|ui|ui.hashed_phone_number=normalize_and_hash_email(raw_record["phone"])endend# Checks if the record has all the required mailing address elements, and if# so, adds a UserIdentifier for the mailing address.unlessraw_record["first_name"].nil?# Checks if the record contains all the other required elements of a# mailing address.required_keys=["last_name","country_code","postal_code"]# Builds a new list of the required keys that are missing from# raw_record.missing_keys=required_keys-raw_record.keysifmissing_keysputs("Skipping addition of mailing address information because the"\"following required keys are missing: #{missing_keys}")elseca.user_identifiers << client.resource.user_identifierdo|ui|ui.address_info=client.resource.offline_user_address_infodo|info|# Certain fields must be hashed using SHA256 in order to handle# identifiers in a privacy-safe way, as described at# https://support.google.com/google-ads/answer/9888656.info.hashed_first_name=normalize_and_hash(raw_record["first_name"])info.hashed_last_name=normalize_and_hash(raw_record["last_name"])info.postal_code=normalize_and_hash(raw_record["country_code"])info.country_code=normalize_and_hash(raw_record["postal_code"])endendendend# Sets optional fields where a value was provided.unlessuser_agent.nil?# Sets the user agent. This should match the user agent of the request# that sent the original conversion so the conversion and its enhancement# are either both attributed as same-device or both attributed as# cross-device.ca.user_agent=user_agentend
# Set the conversion action.$enhancement->{conversionAction}=Google::Ads::GoogleAds::V22::Utils::ResourceNames::conversion_action($customer_id,$raw_record->{conversionActionId});# Set the order ID. Enhancements MUST use order ID instead of GCLID date/time pair.$enhancement->{orderId}=$raw_record->{orderId};# Set the conversion date and time if provided. Providing this value is optional# but recommended.if(defined$raw_record->{conversionDateTime}){$enhancement->{gclidDateTimePair}=Google::Ads::GoogleAds::V22::Services::ConversionAdjustmentUploadService::GclidDateTimePair->new({conversionDateTime=>$raw_record->{conversionDateTime}});}# Set the user agent if provided. This should match the user agent of the# request that sent the original conversion so the conversion and its enhancement# are either both attributed as same-device or both attributed as cross-device.if(defined$raw_record->{userAgent}){$enhancement->{userAgent}=$raw_record->{userAgent};}
# Creates the conversion adjustment upload service client.conversion_adjustment_upload_service=client.get_service("ConversionAdjustmentUploadService")# Uploads the enhancement adjustment. Partial failure should always be set# to true.# NOTE: This request only uploads a single conversion, but if you have# multiple conversions to upload, it's still best to upload them in a single# request. See the following for per-request limits for reference:# https://developers.google.com/google-ads/api/docs/best-practices/quotas#conversion_upload_serviceresponse=conversion_adjustment_upload_service.upload_conversion_adjustments(customer_id=customer_id,conversion_adjustments=[conversion_adjustment],# Enables partial failure (must be true).partial_failure=True,)
response=client.service.conversion_adjustment_upload.upload_conversion_adjustments(customer_id:customer_id,# NOTE: This request only uploads a single conversion, but if you have# multiple conversions to upload, it's still best to upload them in a single# request. See the following for per-request limits for reference:# https://developers.google.com/google-ads/api/docs/best-practices/quotas#conversion_upload_serviceconversion_adjustments:[enhancement],# Partial failure must be set to true.partial_failure:true,)
# Upload the enhancement adjustment. Partial failure should always be set to true.## NOTE: This request contains a single adjustment as a demonstration.# However, if you have multiple adjustments to upload, it's best to# upload multiple adjustments per request instead of sending a separate# request per adjustment. See the following for per-request limits:# https://developers.google.com/google-ads/api/docs/best-practices/quotas#conversion_adjustment_upload_servicemy$response=$api_client->ConversionAdjustmentUploadService()->upload_conversion_adjustments({customerId=>$customer_id,conversionAdjustments=>[$enhancement],# Enable partial failure (must be true).partialFailure=>"true"});