Gérer les conversions hors connexion

Vous pouvez utiliser l'API Google Ads pour importer des conversions hors connexion dans Google Ads. Cela vous permet de suivre les annonces qui ont généré des ventes hors connexion, par exemple par téléphone ou par l'intermédiaire d'un conseiller commercial.

Pour profiter pleinement des avantages de l'importation des données de conversion, nous vous recommandons d'implémenter le suivi avancé des conversions pour les prospects. Il utilise les GCLID et les données fournies par l'utilisateur pour maximiser la durabilité et les performances.

Suivi avancé des conversions

Le suivi avancé des conversions vous aide à mesurer vos conversions avec plus de précision en les complétant avec des données de conversion first party, comme l'adresse e-mail, le numéro de téléphone et l'adresse postale.

Il existe deux types de suivi avancé des conversions. Pour en savoir plus, consultez À propos du suivi avancé des conversions.

La section suivante explique comment améliorer les conversions hors connexion, une fonctionnalité également appelée suivi avancé des conversions pour les prospects.

Qu'est-ce que le suivi avancé des conversions pour les prospects ?

Le suivi avancé des conversions pour les prospects est une version améliorée de l'importation des conversions hors connexion. Il utilise des données fournies par l'utilisateur (les adresses e-mail, par exemple) pour compléter les données importées de conversion hors connexion. Vous pouvez ainsi améliorer la précision de vos mesures et optimiser les performances de vos enchères. Lorsque vous importez vos conversions hors connexion, les données client hachées fournies servent à réattribuer les conversions aux campagnes Google Ads en les faisant correspondre aux mêmes données collectées sur votre site Web (les formulaires de lead, par exemple) et aux clients connectés ayant interagi avec votre annonce. Pour en savoir plus, consultez À propos du suivi avancé des conversions pour les prospects.

Il existe deux façons d'implémenter le suivi avancé des conversions pour les prospects, selon que vous utilisez ou non la balise Google pour suivre les événements d'envoi de formulaire sur votre page Web. Pour des performances et une durabilité optimales, nous vous recommandons d'utiliser la balise Google pour le suivi avancé des conversions pour les prospects.

  • Si vous partez de zéro, commencez par la section Conditions préalables.
  • Si vous avez déjà configuré l'importation des conversions hors connexion et que vous souhaitez passer au suivi avancé des conversions pour les prospects, nous vous recommandons de commencer par la section Configurer le taggage.
  • Si vous avez déjà configuré la balise Google ou si vous ne prévoyez pas de l'utiliser, et que vous commencez à travailler sur l'intégration de l'API Google Ads, passez à la section Implémentation de l'API.
  • Si vous ne parvenez pas à importer les données fournies par l'utilisateur ou si vous utilisez l'attribution externe pour vos conversions, consultez le guide sur l'importation des conversions hors connexion (ancienne version).

Prérequis

Tout d'abord, vérifiez que vous avez suivi les étapes de notre section "Premiers pas".

Vous devez activer le suivi avancé des conversions pour les prospects et accepter les conditions d'utilisation des données client avant de pouvoir l'utiliser. Pour vérifier si ces conditions préalables sont déjà remplies, exécutez la requête suivante pour le client de conversion Google Ads :

SELECT
  customer.id,
  customer.conversion_tracking_setting.accepted_customer_data_terms,
  customer.conversion_tracking_setting.enhanced_conversions_for_leads_enabled
FROM customer

Si accepted_customer_data_terms ou enhanced_conversions_for_leads_enabled est défini sur false, suivez les instructions de Créer une action de conversion pour remplir ces conditions préalables.

Configurer le taggage

Configurez la balise Google pour activer le suivi avancé des conversions pour les prospects en suivant les instructions de la section Configurer les paramètres de la balise Google. Pour configurer le suivi avancé des conversions pour les prospects à l'aide de Google Tag Manager, suivez ces instructions.

Implémentation de l'API

Voici le flux global pour importer le suivi avancé des conversions pour les prospects à l'aide de l'API Google Ads.

  1. Normalisez et hachez les données fournies par l'utilisateur, comme l'adresse e-mail, le numéro de téléphone et l'adresse postale.

  2. Renseignez les objets ClickConversion avec les données fournies par l'utilisateur, normalisées et hachées.

  3. Importez des objets ClickConversion dans l'API Google Ads à l'aide de ConversionUploadService. Pour en savoir plus, consultez UploadClickConversions.

  4. Vérifiez vos importations.

Récupérer le nom de ressource de votre action de conversion

Pour importer des conversions, vous devez spécifier le nom de ressource de l'ConversionAction que vous avez configuré dans Google Ads pour importer les conversions par clic. Vous pouvez trouver le nom de la ressource en interrogeant la ressource conversion_action à l'aide de la requête GAQL suivante :

SELECT
  customer.id,
  conversion_action.id,
  conversion_action.name,
  conversion_action.type,
  conversion_action.resource_name
FROM conversion_action
WHERE conversion_action.type = 'UPLOAD_CLICKS'
  AND conversion_action.status = 'ENABLED'

Normaliser et hacher les données fournies par l'utilisateur

Pour des questions de confidentialité, les données suivantes doivent être hachées au format SHA-256 avant d'être importées :

  • Adresse e-mail
  • Numéro de téléphone
  • Prénom
  • Nom
  • Adresse postale

Ne hachez pas les données suivantes :

  • Pays
  • État
  • Ville
  • Code postal

Afin de standardiser les résultats du hachage, procédez ainsi avant de hacher chacune de ces valeurs :

  • Supprimez les espaces blancs de début et de fin.
  • Convertissez le texte en minuscules.
  • Mettez en forme les numéros de téléphone conformément à la norme E.164.

Format de l'adresse e-mail pour le suivi avancé des conversions

Pour garantir les taux de correspondance les plus élevés pour le suivi avancé des conversions, vous devez formater et hacher correctement les adresses e-mail en procédant comme suit :

  1. Appliquer la normalisation standard (toutes les adresses e-mail) :

    • Supprimez les espaces ASCII de début et de fin.
    • Convertissez tous les caractères de l'adresse e-mail en minuscules.
  2. Appliquer la normalisation spécifique au domaine (gmail.com et googlemail.com uniquement) :

    • Après avoir converti l'adresse e-mail en minuscules, vérifiez si le domaine (après le symbole @) est gmail.com ou googlemail.com.
    • Supprimez les points (.) : dans la partie du nom d'utilisateur (avant le symbole @), supprimez tous les points.
    • Supprimez les suffixes avec le signe plus (+) : dans la partie du nom d'utilisateur, supprimez le premier signe plus (+) et tous les caractères suivants jusqu'au symbole @.
      • Exemple : Jane.Doe+Shopping@googlemail.com devient d'abord jane.doe+shopping@googlemail.com (en minuscules), puis janedoe@googlemail.com (règles Gmail et Googlemail).
    • Autres domaines : pour tout domaine autre que gmail.com ou googlemail.com, ne supprimez pas les points ni les suffixes "plus" du nom d'utilisateur. Appliquez uniquement la normalisation standard (suppression des espaces et conversion en minuscules).
      • Exemple : user.name+NYC@Example.com est normalisé en user.name+nyc@example.com.
  3. Hachez l'adresse e-mail normalisée :

    • Encodez la chaîne d'adresse e-mail normalisée en octets UTF-8.
    • Hachez les octets UTF-8 à l'aide de l'algorithme SHA-256.
    • Formatez le condensé obtenu sous forme de chaîne hexadécimale en minuscules (64 caractères).
import hashlib
import re


def normalize_and_hash_email(email: str) -> str:
    """Normalizes and SHA-256 hashes an email address for enhanced conversions."""
    normalized = email.strip().lower()
    parts = normalized.split("@")
    if len(parts) != 2:
        raise ValueError("Invalid email address format.")
    username, domain = parts
    if domain in ("gmail.com", "googlemail.com"):
        username = username.replace(".", "")
        username = re.sub(r"\+.*$", "", username)
    normalized = f"{username}@{domain}"
    return hashlib.sha256(normalized.encode("utf-8")).hexdigest()

Exemple de code

Cet exemple montre comment normaliser et hacher les données fournies par l'utilisateur.

Java

private String normalizeAndHash(MessageDigest digest, String s)
    throws UnsupportedEncodingException {
  // Normalizes by first converting all characters to lowercase, then trimming spaces.
  String normalized = s.toLowerCase();
  // Removes leading, trailing, and intermediate spaces.
  normalized = normalized.replaceAll("\\s+", "");
  // Hashes the normalized string using the hashing algorithm.
  byte[] hash = digest.digest(normalized.getBytes("UTF-8"));
  StringBuilder result = new StringBuilder();
  for (byte b : hash) {
    result.append(String.format("%02x", b));
  }

  return result.toString();
}

/**
 * Returns the result of normalizing and hashing an email address. For this use case, Google Ads
 * requires removal of any '.' characters or trailing '+' and characters that follow it from the
 * username portion of the email address if the domain is {@code gmail.com} or {@code
 * googlemail.com}.
 *
 * @param digest the digest to use to hash the normalized string.
 * @param emailAddress the email address to normalize and hash.
 */
private String normalizeAndHashEmailAddress(MessageDigest digest, String emailAddress)
    throws UnsupportedEncodingException {
  // Removes all whitespace (leading, trailing, and intermediate) from the email address.
  String normalizedEmail = emailAddress.toLowerCase().replaceAll("\\s+", "");
  String[] emailParts = normalizedEmail.split("@", 2);
  if (emailParts.length == 2 && emailParts[1].matches("^(gmail|googlemail)\\.com$")) {
    // Removes any '.' characters from the portion of the email address before the domain if the
    // domain is gmail.com or googlemail.com.
    emailParts[0] = emailParts[0].replaceAll("\\.", "");
    // Removes any '+' and all characters that follow it from the portion of the email address
    // before the domain if the domain is gmail.com or googlemail.com.
    emailParts[0] = emailParts[0].replaceAll("\\+.*", "");
    normalizedEmail = String.format("%s@%s", emailParts[0], emailParts[1]);
  }
  return normalizeAndHash(digest, normalizedEmail);
}

/**
 * Returns the result of normalizing and hashing a phone number. For this use case, Google Ads
 * requires phone numbers to be in E.164 format.
 *
 * @param digest the digest to use to hash the normalized string.
 * @param phoneNumber the phone number to normalize and hash.
 */
private String normalizeAndHashPhoneNumber(MessageDigest digest, String phoneNumber)
    throws UnsupportedEncodingException {
  // Removes non-digit characters and prepends a leading '+' sign.
  String digitsOnly = phoneNumber.replaceAll("[^0-9]", "");
  String formattedPhone = "+" + digitsOnly;
  if (!formattedPhone.matches("^\\+[1-9]\\d{6,14}$")) {
    throw new IllegalArgumentException("Phone number must be in E.164 format: " + phoneNumber);
  }
  return normalizeAndHash(digest, formattedPhone);
}
      

C#

/// <summary>
/// Normalizes the email address and hashes it. For this use case, Google Ads requires
/// removal of any '.' characters preceding <code>gmail.com</code> or
/// <code>googlemail.com</code>.
/// </summary>
/// <param name="emailAddress">The email address.</param>
/// <returns>The hash code.</returns>
private string NormalizeAndHashEmailAddress(string emailAddress)
{
    string normalizedEmail = emailAddress.ToLower();
    string[] emailParts = normalizedEmail.Split('@');
    if (emailParts.Length > 1 && (emailParts[1] == "gmail.com" ||
        emailParts[1] == "googlemail.com"))
    {
        // Removes any '.' characters from the portion of the email address before
        // the domain if the domain is gmail.com or googlemail.com.
        emailParts[0] = emailParts[0].Replace(".", "");
        normalizedEmail = $"{emailParts[0]}@{emailParts[1]}";
    }
    return NormalizeAndHash(normalizedEmail);
}

/// <summary>
/// Normalizes and hashes a string value.
/// </summary>
/// <param name="value">The value to normalize and hash.</param>
/// <returns>The normalized and hashed value.</returns>
private static string NormalizeAndHash(string value)
{
    return ToSha256String(digest, ToNormalizedValue(value));
}

/// <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>
/// 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();
}
      

PHP

private static function normalizeAndHash(string $hashAlgorithm, string $value): string
{
    // Normalizes by first converting all characters to lowercase, then trimming spaces.
    $normalized = strtolower($value);
    // Removes leading, trailing, and intermediate spaces.
    $normalized = str_replace(' ', '', $normalized);
    return hash($hashAlgorithm, strtolower(trim($normalized)));
}

/**
 * Returns the result of normalizing and hashing an email address. For this use case, Google
 * Ads requires removal of any '.' characters or trailing '+' and characters that follow it
 * from the username portion of the email address if the domain is "gmail.com" or
 * "googlemail.com".
 *
 * @param  string $hashAlgorithm the hash algorithm to use
 * @param  string $emailAddress  the email address to normalize and hash
 * @return string the normalized and hashed email address
 */
private static function normalizeAndHashEmailAddress(
    string $hashAlgorithm,
    string $emailAddress
): string {
    // Removes all whitespace (leading, trailing, and intermediate) from the email address.
    $normalizedEmail = preg_replace('/\s+/', '', strtolower($emailAddress));
    $emailParts = explode('@', $normalizedEmail, 2);
    if (
        count($emailParts) === 2
        && preg_match('/^(gmail|googlemail)\.com$/', $emailParts[1])
    ) {
        // Removes any '.' characters from the portion of the email address before the domain
        // if the domain is gmail.com or googlemail.com.
        $emailParts[0] = str_replace('.', '', $emailParts[0]);
        // Removes any '+' and all characters that follow it from the portion of the email
        // address before the domain if the domain is gmail.com or googlemail.com.
        $emailParts[0] = preg_replace('/\+.*/', '', $emailParts[0]);
        $normalizedEmail = sprintf('%s@%s', $emailParts[0], $emailParts[1]);
    }
    return self::normalizeAndHash($hashAlgorithm, $normalizedEmail);
}

/**
 * Returns the result of normalizing and hashing a phone number. For this use case, Google Ads
 * requires phone numbers to be in E.164 format.
 *
 * @param  string $hashAlgorithm the hash algorithm to use
 * @param  string $phoneNumber   the phone number to normalize and hash
 * @return string the normalized and hashed phone number
 * @throws \InvalidArgumentException if the phone number is not in E.164 format
 */
private static function normalizeAndHashPhoneNumber(
    string $hashAlgorithm,
    string $phoneNumber
): string {
    // Removes non-digit characters and prepends a leading '+' sign.
    $digitsOnly = preg_replace('/[^0-9]/', '', $phoneNumber);
    $formattedPhone = '+' . $digitsOnly;
    if (!preg_match('/^\+[1-9]\d{6,14}$/', $formattedPhone)) {
        throw new \InvalidArgumentException(
            "Phone number must be in E.164 format: $phoneNumber"
        );
    }
    return self::normalizeAndHash($hashAlgorithm, $formattedPhone);
}
      

Python

def normalize_and_hash_email_address(email_address: str) -> str:
    """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: str = email_address.strip().lower()
    email_parts: list[str] = normalized_email.split("@")

    # Check that there are at least two segments
    if len(email_parts) > 1:
        # Removes any '.' and '+' characters from the portion of the email address
        # before the domain
        chars_to_remove = ".+"
        translation_table = str.maketrans("", "", chars_to_remove)
        email_parts[0] = email_parts[0].translate(translation_table)
        normalized_email = "@".join(email_parts)

    return normalize_and_hash(normalized_email)


def normalize_and_hash(s: str) -> str:
    """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/7474263

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

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

Ruby

# 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/7474263.
def normalize_and_hash(str)
  # Remove leading and trailing whitespace and ensure all letters are lowercase
  # before hashing.
  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'.
def normalize_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.
  if email_parts.last =~ /^(gmail|googlemail)\.com\s*/
    email_parts[0] = email_parts[0].gsub('.', '')
  end
  normalize_and_hash(email_parts.join('@'))
end
      

Perl

sub normalize_and_hash {
  my $value = shift;

  # Removes leading, trailing, and intermediate spaces.
  $value =~ s/\s+//g;
  return sha256_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'.
sub normalize_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];
  }
  return normalize_and_hash($normalized_email);
}
      

curl

Renseigner les objets ClickConversion

La collection d'objets ClickConversion dans votre UploadClickConversionsRequest représente l'ensemble des conversions que vous souhaitez importer. Tenez compte des informations suivantes lorsque vous créez des objets ClickConversion :

gclid

Les GCLID sont des identifiants capturés à partir des paramètres d'URL lorsqu'un utilisateur clique sur votre annonce et accède à votre site Web.

gbraid

Un gbraid est un paramètre d'URL qui est présent lorsqu'un utilisateur clique sur une annonce sur le Web et est redirigé vers votre application iOS.

wbraid

Un wbraid est un paramètre d'URL qui est présent lorsqu'un utilisateur clique sur une annonce dans une application iOS et est redirigé vers votre page Web.

cart_data

Contient des informations sur une conversion au niveau de l'article. Vous devez renseigner le champ cart_data pour générer des rapports sur les données de panier (articles achetés, prix et quantité, par exemple) dans l'UI Google Ads. Consultez la définition de l'objet CartData pour connaître la structure requise, et lisez À propos des conversions avec les données du panier pour en savoir plus.

user_identifiers

Lorsque vous utilisez le suivi avancé des conversions pour les prospects, vous devez renseigner le champ user_identifiers avec des données fournies par l'utilisateur normalisées et hachées. Si vous disposez de plusieurs identifiants utilisateur, créez un UserIdentifier distinct pour chacun d'eux (jusqu'à cinq identifiants).

conversion_date_time

Date et heure de la conversion.

La valeur doit comporter un fuseau horaire et respecter le format yyyy-mm-dd HH:mm:ss+|-HH:mm, par exemple 2022-01-01 19:32:45-05:00 (sans tenir compte de l'heure d'été).

Le fuseau horaire peut correspondre à n'importe quelle valeur valide. Il n'est pas nécessaire qu'il corresponde à celui du compte. Toutefois, si vous prévoyez de comparer vos données de conversion importées avec celles de l'interface utilisateur Google Ads, nous vous recommandons d'utiliser le même fuseau horaire que votre compte Google Ads afin que le nombre de conversions corresponde. Pour en savoir plus et obtenir des exemples, consultez Préparer les données pour l'importation et Codes et formats pour obtenir la liste des ID de fuseau horaire valides.

conversion_action

Nom de ressource de l'élément ConversionAction pour la conversion hors connexion.

L'action de conversion doit avoir une type de UPLOAD_CLICKS et doit exister dans le client de conversion Google Ads du compte Google Ads associé au clic.

conversion_value

Valeur de la conversion.

currency_code

Le code de la devise de conversion_value.

consent

Nous vous recommandons vivement de renseigner le champ consent de l'objet ClickConversion. Si vous ne le définissez pas, il est possible que vos conversions ne soient pas attribuables.

order_id

Également appelé "ID de transaction" pour la conversion. Ce champ est facultatif, mais vivement recommandé, car il permet de référencer plus facilement les conversions importées lorsque vous effectuez des ajustements. Si vous l'avez défini lors de l'importation, vous devez l'utiliser pour tous les ajustements. Pour savoir comment utiliser un ID de transaction afin de limiter le nombre de conversions en double, consultez Limiter le nombre de conversions en double à l'aide d'un ID de transaction.

custom_variables

Valeurs des variables de conversion personnalisées. Google Ads n'accepte pas les variables de conversion personnalisées en combinaison avec wbraid ou gbraid.

conversion_environment

Indique l'environnement dans lequel cette conversion a été enregistrée. Par exemple, APP ou WEB.

session_attributes_encoded et session_attributes_key_value_pairs

Les attributs de session représentent des identifiants agrégés utilisés pour l'attribution des conversions. Ils s'ajoutent aux GCLID, aux paramètres d'URL (comme les GBRAID) et aux données fournies par l'utilisateur, qui sont essentiels pour le suivi avancé des conversions pour les prospects. Il existe deux façons d'importer des attributs de session : en fournissant le jeton encodé généré par notre code JavaScript dans le navigateur, ou en fournissant des paires clé-valeur individuelles pour chacun des identifiants.

Pour maximiser les performances de vos campagnes, nous vous recommandons d'importer les identifiants de clic, les données fournies par l'utilisateur et les attributs de session avec toutes vos conversions, si possible.

Java

// Sets one of the sessionAttributesEncoded or sessionAttributesKeyValuePairs if either is
// provided. The session attribute fields are only available to allowlisted users.
// To include these fields in conversion imports, upgrade to the Data Manager API.
if (rawRecord.containsKey("sessionAttributesEncoded")) {
  clickConversionBuilder.setSessionAttributesEncoded(
      ByteString.copyFromUtf8(rawRecord.get("sessionAttributesEncoded")));
} else if (rawRecord.containsKey("sessionAttributesMap")) {
  List<String> pairings =
      Arrays.stream(rawRecord.get("sessionAttributesMap").split(" "))
          .map(String::trim)
          .collect(Collectors.toList());
  SessionAttributesKeyValuePairs.Builder sessionAttributePairs =
      SessionAttributesKeyValuePairs.newBuilder();
  for (String pair : pairings) {
    String[] parts = pair.split("=", 2);
    if (parts.length != 2) {
      throw new IllegalArgumentException(
          "Failed to read the sessionAttributesMap. SessionAttributesMap must use a"
              + " space-delimited list of session attribute key value pairs. Each pair should"
              + " be separated by an equal sign, for example: 'gad_campaignid=12345"
              + " gad_source=1'");
    }
    sessionAttributePairs.addKeyValuePairs(
        SessionAttributeKeyValuePair.newBuilder()
            .setSessionAttributeKey(parts[0])
            .setSessionAttributeValue(parts[1])
            .build());
  }
  clickConversionBuilder.setSessionAttributesKeyValuePairs(sessionAttributePairs.build());
}
      

C#

// The session attribute fields are only available to allowlisted users. To
// include these fields in conversion imports, upgrade to the Data Manager API.
if (!string.IsNullOrEmpty(sessionAttributesEncoded))
{
    clickConversion.SessionAttributesEncoded =
        ByteString.CopyFrom(sessionAttributesEncoded, Encoding.Unicode);
}
else if (!string.IsNullOrEmpty(sessionAttributes))
{
    IEnumerable<SessionAttributeKeyValuePair> parsedSessionAttributes =
        sessionAttributes.Split(';').Select(pair => {
            string[] split = pair.Split('=');
            return new SessionAttributeKeyValuePair()
            {
                SessionAttributeKey = split[0],
                SessionAttributeValue = split[1]
            };
        });

    clickConversion.SessionAttributesKeyValuePairs =
        new SessionAttributesKeyValuePairs();
    clickConversion.SessionAttributesKeyValuePairs.KeyValuePairs
        .AddRange(parsedSessionAttributes);
}
      

PHP

This example is not yet available in PHP; you can take a look at the other languages.
    

Python

# Set one of the session_attributes_encoded or
# session_attributes_key_value_pairs fields if either are provided.
# The session attribute fields are only available to allowlisted users.
# To include these fields in conversion imports, upgrade to the Data Manager API.
if session_attributes_encoded:
    click_conversion.session_attributes_encoded = session_attributes_encoded
elif session_attributes_dict:
    for key, value in session_attributes_dict.items():
        pair: SessionAttributeKeyValuePair = client.get_type(
            "SessionAttributeKeyValuePair"
        )
        pair.session_attribute_key = key
        pair.session_attribute_value = value
        click_conversion.session_attributes_key_value_pairs.key_value_pairs.append(
            pair
        )
      

Ruby

# Set one of the session_attributes_encoded or
# session_attributes_key_value_pairs fields if either are provided.
# The session attribute fields are only available to allowlisted users.
# To include these fields in conversion imports, upgrade to the Data Manager API.
if session_attributes_encoded != nil
  cc.class.module_eval { attr_accessor :session_attributes_encoded}
  cc.session_attributes_encoded = session_attributes_encoded
elsif session_attributes_hash != nil
  # Add new attribute to click conversion object
  cc.class.module_eval { attr_accessor :session_attributes_key_value_pairs}
  cc.session_attributes_key_value_pairs = ::Google::Ads::GoogleAds::V19::Services::SessionAttributesKeyValuePairs.new

  # Loop thru inputted session_attributes_hash to populate session_attributes_key_value_pairs
  session_attributes_hash.each do |key, value|
    pair = ::Google::Ads::GoogleAds::V19::Services::SessionAttributeKeyValuePair.new
    pair.session_attribute_key = key
    pair.session_attribute_value = value
    cc.session_attributes_key_value_pairs.key_value_pairs << pair
  end
end    
      

Perl

# Set one of the session_attributes_encoded or session_attributes_key_value_pairs
# fields if either are provided.
if (defined $session_attributes_encoded) {
  $click_conversion->{sessionAttributesEncoded} = $session_attributes_encoded;
} elsif (defined $session_attributes_hash) {
  while (my ($key, $value) = each %$session_attributes_hash) {
    my $pair =
      Google::Ads::GoogleAds::V25::Services::ConversionUploadService::SessionAttributeKeyValuePair
      ->new({sessionAttributeKey => $key, sessionAttributeValue => $value});
    push @{$click_conversion->{sessionAttributesKeyValuePairs}{keyValuePairs}
    }, $pair;
  }
}
      

curl

user_ip_address

Adresse IP du client lorsqu'il est arrivé sur la page de destination après un clic sur une annonce et avant un événement de conversion. Il s'agit de l'adresse IP de l'appareil du client, et non celle du serveur de l'annonceur.

Ce champ est une chaîne représentant une adresse IP au format IPv4 ou IPv6. Exemple :

  • IPv4 : "192.0.2.0"
  • IPv6 : "2001:0DB8:1234:5678:9999:1111:0000:0001"

Exemple de code

Cet exemple montre comment définir vos données normalisées et hachées fournies par l'utilisateur sur un objet ClickConversion.

Java

// Creates an empty builder for constructing the click conversion.
ClickConversion.Builder clickConversionBuilder = ClickConversion.newBuilder();

// Extracts user email and phone 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
// hashedEmail, hashedPhoneNumber, mobileId, thirdPartyUserId, or addressInfo. 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 hashedPhoneNumber.
//
// UserIdentifier incorrectlyPopulatedUserIdentifier =
//     UserIdentifier.newBuilder()
//         .setHashedEmail("...")
//         .setHashedPhoneNumber("...")
//         .build();

ImmutableMap.Builder<String, String> rawRecordBuilder =
    ImmutableMap.<String, String>builder()
        .put("email", "alex.2+myalias@gmail.com")
        // Phone number to be converted to E.164 format, with a leading '+' as required.
        .put("phone", "+1 (800) 555-0102")
        // This example lets you put 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.
        .put("conversionActionId", Long.toString(conversionActionId))
        .put("conversionDateTime", conversionDateTime)
        .put("conversionValue", Double.toString(conversionValue))
        .put("currencyCode", "USD");

// Adds entries for the optional fields.
if (orderId != null) {
  rawRecordBuilder.put("orderId", orderId);
}
if (gclid != null) {
  rawRecordBuilder.put("gclid", gclid);
}
if (adUserDataConsent != null) {
  rawRecordBuilder.put("adUserDataConsent", adUserDataConsent.name());
}
if (sessionAttributesEncoded != null) {
  rawRecordBuilder.put("sessionAttributesEncoded", sessionAttributesEncoded);
}
if (sessionAttributesMap != null) {
  rawRecordBuilder.put("sessionAttributesMap", sessionAttributesMap);
}

// Builds the map representing the record.
Map<String, String> rawRecord = rawRecordBuilder.build();

// Creates a SHA256 message digest for hashing user identifiers in a privacy-safe way, as
// described at https://support.google.com/google-ads/answer/9888656.
MessageDigest sha256Digest = MessageDigest.getInstance("SHA-256");

// Creates a list for the user identifiers.
List<UserIdentifier> userIdentifiers = new ArrayList<>();

// Creates a user identifier using the hashed email address, using the normalize and hash method
// specifically for email addresses.
UserIdentifier emailIdentifier =
    UserIdentifier.newBuilder()
        // Optional: specify the user identifier source.
        .setUserIdentifierSource(UserIdentifierSource.FIRST_PARTY)
        // Uses the normalize and hash method specifically for email addresses.
        .setHashedEmail(normalizeAndHashEmailAddress(sha256Digest, rawRecord.get("email")))
        .build();
userIdentifiers.add(emailIdentifier);

// Creates a user identifier using normalized and hashed phone info.
UserIdentifier hashedPhoneNumberIdentifier =
    UserIdentifier.newBuilder()
        .setHashedPhoneNumber(normalizeAndHashPhoneNumber(sha256Digest, rawRecord.get("phone")))
        .build();
// Adds the hashed phone number identifier to the UserData object's list.
userIdentifiers.add(hashedPhoneNumberIdentifier);

// Adds the user identifiers to the conversion.
clickConversionBuilder.addAllUserIdentifiers(userIdentifiers);
      

C#

// Adds a user identifier using the hashed email address, using the normalize
// and hash method specifically for email addresses.
clickConversion.UserIdentifiers.Add(new UserIdentifier()
{
    HashedEmail = NormalizeAndHashEmailAddress("alex.2@example.com"),
    // Optional: Specifies the user identifier source.
    UserIdentifierSource = UserIdentifierSource.FirstParty
});

// Adds a user identifier using normalized and hashed phone info.
clickConversion.UserIdentifiers.Add(new UserIdentifier()
{
    HashedPhoneNumber = NormalizeAndHash("+1 800 5550102"),
    // Optional: Specifies the user identifier source.
    UserIdentifierSource = UserIdentifierSource.FirstParty
});

// Adds a user identifier with all the required mailing address elements.
clickConversion.UserIdentifiers.Add(new UserIdentifier()
{
    AddressInfo = new OfflineUserAddressInfo()
    {
        // FirstName and LastName must be normalized and hashed.
        HashedFirstName = NormalizeAndHash("Alex"),
        HashedLastName = NormalizeAndHash("Quinn"),
        // CountryCode and PostalCode are sent in plain text.
        CountryCode = "US",
        PostalCode = "94045"
    }
});
      

PHP

// Creates a click conversion with the specified attributes.
$clickConversion = new ClickConversion();

// Extract user email and phone from the raw data, normalize and hash it, then wrap 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 hashedEmail, hashedPhoneNumber, mobileId, thirdPartyUserId, or addressInfo. 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 hashedPhoneNumber.
//
// $incorrectlyPopulatedUserIdentifier = new UserIdentifier([
//    'hashed_email' => '...',
//    'hashed_phone_number' => '...'
// ]);

$rawRecord = [
    // Email address that includes a period (.) and plus (+) suffix before the Gmail domain.
    'email' => 'alex.2+myalias@gmail.com',
    // Phone number to be converted to E.164 format, with a leading '+' as required.
    'phone' => '+1 (800) 555-0102',
    // 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' => $orderId,
    'gclid' => $gclid,
    'conversionActionId' => $conversionActionId,
    'conversionDateTime' => $conversionDateTime,
    'conversionValue' => $conversionValue,
    'currencyCode' => 'USD',
    'adUserDataConsent' => $adUserDataConsent,
    'sessionAttributesEncoded' => $sessionAttributesEncoded,
    'sessionAttributesDict' => $sessionAttributesDict
];

// Creates a list for the user identifiers.
$userIdentifiers = [];

// Uses the SHA-256 hash algorithm for hashing user identifiers in a privacy-safe way, as
// described at https://support.google.com/google-ads/answer/9888656.
$hashAlgorithm = "sha256";

// Creates a user identifier using the hashed email address, using the normalize and hash
// method specifically for email addresses.
$emailIdentifier = new UserIdentifier(
    [
    // Uses the normalize and hash method specifically for email addresses.
    'hashed_email' => self::normalizeAndHashEmailAddress(
        $hashAlgorithm,
        $rawRecord['email']
    ),
    // Optional: Specifies the user identifier source.
    'user_identifier_source' => UserIdentifierSource::FIRST_PARTY
    ]
);
$userIdentifiers[] = $emailIdentifier;

// Checks if the record has a phone number, and if so, adds a UserIdentifier for it.
if (array_key_exists('phone', $rawRecord)) {
    $hashedPhoneNumberIdentifier = new UserIdentifier(
        [
        'hashed_phone_number' => self::normalizeAndHashPhoneNumber(
            $hashAlgorithm,
            $rawRecord['phone']
        )
        ]
    );
    // Adds the hashed phone number identifier to the user identifiers list.
    $userIdentifiers[] = $hashedPhoneNumberIdentifier;
}

// Adds the user identifiers to the conversion.
$clickConversion->setUserIdentifiers($userIdentifiers);
      

Python

# Extract user email and phone 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:
#
# incorrectly_populated_user_identifier = client.get_type("UserIdentifier")
# incorrectly_populated_user_identifier.hashed_email = "...""
# incorrectly_populated_user_identifier.hashed_phone_number = "...""

raw_record: Dict[str, Union[str, float]] = {
    # Email address that includes a period (.) before the Gmail domain.
    "email": "alex.2@example.com",
    # 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,
    "gclid": gclid,
    "conversion_action_id": conversion_action_id,
    "conversion_date_time": conversion_date_time,
    "conversion_value": conversion_value,
    "currency_code": "USD",
    "ad_user_data_consent": ad_user_data_consent,
}

# Constructs the click conversion.
click_conversion: ClickConversion = client.get_type("ClickConversion")
# Creates a user identifier using the hashed email address, using the
# normalize and hash method specifically for email addresses.
email_identifier: UserIdentifier = 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 user identifier to the conversion.
click_conversion.user_identifiers.append(email_identifier)

# Checks if the record has a phone number, and if so, adds a UserIdentifier
# for it.
if raw_record.get("phone") is not None:
    phone_identifier: UserIdentifier = client.get_type("UserIdentifier")
    phone_identifier.hashed_phone_number = normalize_and_hash(
        raw_record["phone"]
    )
    # Adds the phone identifier to the conversion adjustment.
    click_conversion.user_identifiers.append(phone_identifier)
      

Ruby

# Extract user email and phone 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:
#
# 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",
  # 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,
  "gclid" => gclid,
  "conversion_action_id" => conversion_action_id,
  "conversion_date_time" => conversion_date_time,
  "conversion_value" => conversion_value,
  "currency_code" => "USD",
  "ad_user_data_consent" => ad_user_data_consent,
  "session_attributes_encoded" => session_attributes_encoded,
  "session_attributes_hash" => session_attributes_hash
}

click_conversion = client.resource.click_conversion do |cc|
  cc.conversion_action = client.path.conversion_action(customer_id, conversion_action_id)
  cc.conversion_date_time = conversion_date_time
  cc.conversion_value = conversion_value.to_f
  cc.currency_code = 'USD'

  unless order_id.nil?
    cc.order_id = order_id
  end

  unless raw_record["gclid"].nil?
    cc.gclid = gclid
  end

  # Specifies whether user consent was obtained for the data you are
  # uploading. For more details, see:
  # https://www.google.com/about/company/user-consent-policy
  unless raw_record["ad_user_data_consent"].nil?
    cc.consent = client.resource.consent do |c|
      c.ad_user_data = ad_user_data_consent
    end
  end

  # Set one of the session_attributes_encoded or
  # session_attributes_key_value_pairs fields if either are provided.
  # The session attribute fields are only available to allowlisted users.
  # To include these fields in conversion imports, upgrade to the Data Manager API.
  if session_attributes_encoded != nil
    cc.class.module_eval { attr_accessor :session_attributes_encoded}
    cc.session_attributes_encoded = session_attributes_encoded
  elsif session_attributes_hash != nil
    # Add new attribute to click conversion object
    cc.class.module_eval { attr_accessor :session_attributes_key_value_pairs}
    cc.session_attributes_key_value_pairs = ::Google::Ads::GoogleAds::V19::Services::SessionAttributesKeyValuePairs.new

    # Loop thru inputted session_attributes_hash to populate session_attributes_key_value_pairs
    session_attributes_hash.each do |key, value|
      pair = ::Google::Ads::GoogleAds::V19::Services::SessionAttributeKeyValuePair.new
      pair.session_attribute_key = key
      pair.session_attribute_value = value
      cc.session_attributes_key_value_pairs.key_value_pairs << pair
    end
  end    

  # Creates a user identifier using the hashed email address, using the
  # normalize and hash method specifically for email addresses.
  # If using a phone number, use the normalize_and_hash method instead.
  cc.user_identifiers << client.resource.user_identifier do |ui|
    ui.hashed_email = normalize_and_hash_email(raw_record["email"])
    # Optional: Specifies the user identifier source.
    ui.user_identifier_source = :FIRST_PARTY
  end

  # Checks if the record has a phone number, and if so, adds a UserIdentifier
  # for it.
  unless raw_record["phone"].nil?
    cc.user_identifiers << client.resource.user_identifier do |ui|
      ui.hashed_phone_number = normalize_and_hash(raw_record["phone"])
    end
  end
end
      

Perl

# Create an empty click conversion.
my $click_conversion =
  Google::Ads::GoogleAds::V25::Services::ConversionUploadService::ClickConversion
  ->new({});

# Extract user email and phone 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::V25::Common::UserIdentifier->new({
#   hashedEmail => '...',
#   hashedPhoneNumber => '...',
# });
my $raw_record = {
  # Email address that includes a period (.) before the Gmail domain.
  email => 'alex.2@example.com',
  # 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,
  gclid              => $gclid,
  conversionActionId => $conversion_action_id,
  conversionDateTime => $conversion_date_time,
  conversionValue    => $conversion_value,
  currencyCode       => "USD",
  adUserDataConsent  => $ad_user_data_consent
};
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::V25::Common::UserIdentifier->new({
      hashedEmail => $hashed_email,
      # Optional: Specify the user identifier source.
      userIdentifierSource => FIRST_PARTY
    }));

# Create a user identifier using normalized and hashed phone info.
my $hashed_phone = normalize_and_hash($raw_record->{phone});
push(
  @$user_identifiers,
  Google::Ads::GoogleAds::V25::Common::UserIdentifier->new({
      hashedPhone => $hashed_phone,
      # Optional: Specify the user identifier source.
      userIdentifierSource => FIRST_PARTY
    }));

# Add the user identifiers to the conversion.
$click_conversion->{userIdentifiers} = $user_identifiers;
      

curl

Cet exemple montre comment définir d'autres champs nécessaires sur un objet ClickConversion.

Java

// Adds details of the conversion.
clickConversionBuilder.setConversionAction(
    ResourceNames.conversionAction(
        customerId, Long.parseLong(rawRecord.get("conversionActionId"))));
clickConversionBuilder.setConversionDateTime(rawRecord.get("conversionDateTime"));
clickConversionBuilder.setConversionValue(Double.parseDouble(rawRecord.get("conversionValue")));
clickConversionBuilder.setCurrencyCode(rawRecord.get("currencyCode"));

// Sets the order ID if provided.
if (rawRecord.containsKey("orderId")) {
  clickConversionBuilder.setOrderId(rawRecord.get("orderId"));
}

// Sets the Google click ID (gclid) if provided.
if (rawRecord.containsKey("gclid")) {
  clickConversionBuilder.setGclid(rawRecord.get("gclid"));
}

// Sets the consent information, if provided.
if (rawRecord.containsKey("adUserDataConsent")) {
  // Specifies whether user consent was obtained for the data you are uploading. See
  // https://www.google.com/about/company/user-consent-policy for details.
  clickConversionBuilder.setConsent(
      Consent.newBuilder()
          .setAdUserData(ConsentStatus.valueOf(rawRecord.get("adUserDataConsent"))));
}

// Sets one of the sessionAttributesEncoded or sessionAttributesKeyValuePairs if either is
// provided. The session attribute fields are only available to allowlisted users.
// To include these fields in conversion imports, upgrade to the Data Manager API.
if (rawRecord.containsKey("sessionAttributesEncoded")) {
  clickConversionBuilder.setSessionAttributesEncoded(
      ByteString.copyFromUtf8(rawRecord.get("sessionAttributesEncoded")));
} else if (rawRecord.containsKey("sessionAttributesMap")) {
  List<String> pairings =
      Arrays.stream(rawRecord.get("sessionAttributesMap").split(" "))
          .map(String::trim)
          .collect(Collectors.toList());
  SessionAttributesKeyValuePairs.Builder sessionAttributePairs =
      SessionAttributesKeyValuePairs.newBuilder();
  for (String pair : pairings) {
    String[] parts = pair.split("=", 2);
    if (parts.length != 2) {
      throw new IllegalArgumentException(
          "Failed to read the sessionAttributesMap. SessionAttributesMap must use a"
              + " space-delimited list of session attribute key value pairs. Each pair should"
              + " be separated by an equal sign, for example: 'gad_campaignid=12345"
              + " gad_source=1'");
    }
    sessionAttributePairs.addKeyValuePairs(
        SessionAttributeKeyValuePair.newBuilder()
            .setSessionAttributeKey(parts[0])
            .setSessionAttributeValue(parts[1])
            .build());
  }
  clickConversionBuilder.setSessionAttributesKeyValuePairs(sessionAttributePairs.build());
}

// Calls build to build the conversion.
ClickConversion clickConversion = clickConversionBuilder.build();
      

C#

// Adds details of the conversion.
clickConversion.ConversionAction =
    ResourceNames.ConversionAction(customerId, conversionActionId);
clickConversion.ConversionDateTime = conversionDateTime;
clickConversion.ConversionValue = conversionValue;
clickConversion.CurrencyCode = "USD";

// Sets the order ID if provided.
if (!string.IsNullOrEmpty(orderId))
{
    clickConversion.OrderId = orderId;
}

// Sets the Google click ID (gclid) if provided.
if (!string.IsNullOrEmpty(gclid))
{
    clickConversion.Gclid = gclid;
}

// The session attribute fields are only available to allowlisted users. To
// include these fields in conversion imports, upgrade to the Data Manager API.
if (!string.IsNullOrEmpty(sessionAttributesEncoded))
{
    clickConversion.SessionAttributesEncoded =
        ByteString.CopyFrom(sessionAttributesEncoded, Encoding.Unicode);
}
else if (!string.IsNullOrEmpty(sessionAttributes))
{
    IEnumerable<SessionAttributeKeyValuePair> parsedSessionAttributes =
        sessionAttributes.Split(';').Select(pair => {
            string[] split = pair.Split('=');
            return new SessionAttributeKeyValuePair()
            {
                SessionAttributeKey = split[0],
                SessionAttributeValue = split[1]
            };
        });

    clickConversion.SessionAttributesKeyValuePairs =
        new SessionAttributesKeyValuePairs();
    clickConversion.SessionAttributesKeyValuePairs.KeyValuePairs
        .AddRange(parsedSessionAttributes);
}

      

PHP

// Adds details of the conversion.
$clickConversion->setConversionAction(
    ResourceNames::forConversionAction($customerId, $rawRecord['conversionActionId'])
);
$clickConversion->setConversionDateTime($rawRecord['conversionDateTime']);
$clickConversion->setConversionValue($rawRecord['conversionValue']);
$clickConversion->setCurrencyCode($rawRecord['currencyCode']);

// Sets the order ID if provided.
if (!empty($rawRecord['orderId'])) {
    $clickConversion->setOrderId($rawRecord['orderId']);
}

// Sets the Google click ID (gclid) if provided.
if (!empty($rawRecord['gclid'])) {
    $clickConversion->setGclid($rawRecord['gclid']);
}

// Sets the ad user data consent if provided.
if (!empty($rawRecord['adUserDataConsent'])) {
    // Specifies whether user consent was obtained for the data you are uploading. See
    // https://www.google.com/about/company/user-consent-policy for details.
    $clickConversion->setConsent(
        new Consent(['ad_user_data' => $rawRecord['adUserDataConsent']])
    );
}

// Set one of the sessionAttributesEncoded or
// SessionAttributeKeyValuePair fields if either are provided. The session attribute
// fields are only available to allowlisted users. To include these fields in conversion
// imports, upgrade to the Data Manager API.
if (!empty($sessionAttributesEncoded)) {
    $clickConversion->setSessionAttributesEncoded($sessionAttributesEncoded);
} elseif (!empty($sessionAttributesDict)) {
    // Create a new container object to hold key-value pairs.
    $sessionAttributesKeyValuePairs = new SessionAttributesKeyValuePairs();
    // Initialize an array to hold individual key-value pair messages.
    $keyValuePairs = [];
    // Append each key-value pair provided to the $keyValuePairs array
    foreach ($sessionAttributesDict as $key => $value) {
        $pair = new SessionAttributeKeyValuePair();
        $pair->setSessionAttributeKey($key);
        $pair->setSessionAttributeValue($value);
        $keyValuePairs[] = $pair;
    }
    // Set the the full list of key-value pairs on the container object.
    $sessionAttributesKeyValuePairs->setKeyValuePairs($keyValuePairs);
    // Attach the container of key-value pairs to the ClickConversion object.
    $clickConversion->setSessionAttributesKeyValuePairs($sessionAttributesKeyValuePairs);
}
      

Python

# Add details of the conversion.
# Gets the conversion action resource name.
conversion_action_service: ConversionActionServiceClient = (
    client.get_service("ConversionActionService")
)
click_conversion.conversion_action = (
    conversion_action_service.conversion_action_path(
        customer_id, raw_record["conversion_action_id"]
    )
)
click_conversion.conversion_date_time = raw_record["conversion_date_time"]
click_conversion.conversion_value = raw_record["conversion_value"]
click_conversion.currency_code = raw_record["currency_code"]

# Sets the order ID if provided.
if raw_record.get("order_id"):
    click_conversion.order_id = raw_record["order_id"]

# Sets the gclid if provided.
if raw_record.get("gclid"):
    click_conversion.gclid = raw_record["gclid"]

# Specifies whether user consent was obtained for the data you are
# uploading. For more details, see:
# https://www.google.com/about/company/user-consent-policy
if raw_record["ad_user_data_consent"]:
    click_conversion.consent.ad_user_data = client.enums.ConsentStatusEnum[
        raw_record["ad_user_data_consent"]
    ]

# Set one of the session_attributes_encoded or
# session_attributes_key_value_pairs fields if either are provided.
# The session attribute fields are only available to allowlisted users.
# To include these fields in conversion imports, upgrade to the Data Manager API.
if session_attributes_encoded:
    click_conversion.session_attributes_encoded = session_attributes_encoded
elif session_attributes_dict:
    for key, value in session_attributes_dict.items():
        pair: SessionAttributeKeyValuePair = client.get_type(
            "SessionAttributeKeyValuePair"
        )
        pair.session_attribute_key = key
        pair.session_attribute_value = value
        click_conversion.session_attributes_key_value_pairs.key_value_pairs.append(
            pair
        )
      

Ruby

cc.conversion_action = client.path.conversion_action(customer_id, conversion_action_id)
cc.conversion_date_time = conversion_date_time
cc.conversion_value = conversion_value.to_f
cc.currency_code = 'USD'

unless order_id.nil?
  cc.order_id = order_id
end

unless raw_record["gclid"].nil?
  cc.gclid = gclid
end

# Specifies whether user consent was obtained for the data you are
# uploading. For more details, see:
# https://www.google.com/about/company/user-consent-policy
unless raw_record["ad_user_data_consent"].nil?
  cc.consent = client.resource.consent do |c|
    c.ad_user_data = ad_user_data_consent
  end
end

# Set one of the session_attributes_encoded or
# session_attributes_key_value_pairs fields if either are provided.
# The session attribute fields are only available to allowlisted users.
# To include these fields in conversion imports, upgrade to the Data Manager API.
if session_attributes_encoded != nil
  cc.class.module_eval { attr_accessor :session_attributes_encoded}
  cc.session_attributes_encoded = session_attributes_encoded
elsif session_attributes_hash != nil
  # Add new attribute to click conversion object
  cc.class.module_eval { attr_accessor :session_attributes_key_value_pairs}
  cc.session_attributes_key_value_pairs = ::Google::Ads::GoogleAds::V19::Services::SessionAttributesKeyValuePairs.new

  # Loop thru inputted session_attributes_hash to populate session_attributes_key_value_pairs
  session_attributes_hash.each do |key, value|
    pair = ::Google::Ads::GoogleAds::V19::Services::SessionAttributeKeyValuePair.new
    pair.session_attribute_key = key
    pair.session_attribute_value = value
    cc.session_attributes_key_value_pairs.key_value_pairs << pair
  end
end    
      

Perl

# Add details of the conversion.
$click_conversion->{conversionAction} =
  Google::Ads::GoogleAds::V25::Utils::ResourceNames::conversion_action(
  $customer_id, $raw_record->{conversionActionId});
$click_conversion->{conversionDateTime} = $raw_record->{conversionDateTime};
$click_conversion->{conversionValue}    = $raw_record->{conversionValue};
$click_conversion->{currencyCode}       = $raw_record->{currencyCode};

# Set the order ID if provided.
if (defined $raw_record->{orderId}) {
  $click_conversion->{orderId} = $raw_record->{orderId};
}

# Set the Google click ID (gclid) if provided.
if (defined $raw_record->{gclid}) {
  $click_conversion->{gclid} = $raw_record->{gclid};
}

# Set the consent information, if provided.
if (defined $raw_record->{adUserDataConsent}) {
  $click_conversion->{consent} =
    Google::Ads::GoogleAds::V25::Common::Consent->new({
      adUserData => $raw_record->{adUserDataConsent}});
}

# Set one of the session_attributes_encoded or session_attributes_key_value_pairs
# fields if either are provided.
if (defined $session_attributes_encoded) {
  $click_conversion->{sessionAttributesEncoded} = $session_attributes_encoded;
} elsif (defined $session_attributes_hash) {
  while (my ($key, $value) = each %$session_attributes_hash) {
    my $pair =
      Google::Ads::GoogleAds::V25::Services::ConversionUploadService::SessionAttributeKeyValuePair
      ->new({sessionAttributeKey => $key, sessionAttributeValue => $value});
    push @{$click_conversion->{sessionAttributesKeyValuePairs}{keyValuePairs}
    }, $pair;
  }
}
      

curl

Créer la requête

Une fois vos objets ClickConversion configurés et ajoutés au champ conversions de l'objet UploadClickConversionsRequest, définissez les champs suivants et transmettez la requête à la méthode UploadClickConversions sur ConversionUploadService.

customer_id
Définissez ce paramètre sur le client de conversion Google Ads du compte qui est la source des clics. Si vous ne savez pas quel compte est le bon, reportez-vous au champ customer.conversion_tracking_setting.google_ads_conversion_customer de l'exemple de requête dans la section Premiers pas.
job_id

Fournit un mécanisme permettant d'associer vos demandes d'importation aux informations par tâche dans les diagnostics des données hors connexion.

Si vous ne définissez pas ce champ, l'API Google Ads attribue à chaque requête une valeur unique comprise dans la plage [2^31, 2^63). Si vous préférez regrouper plusieurs requêtes dans un seul job logique, définissez ce champ sur la même valeur dans la plage [0, 2^31) pour chaque requête de votre job.

Le champ job_id de la réponse contient l'ID du job pour la requête, que vous ayez spécifié une valeur ou que vous ayez laissé l'API Google Ads en attribuer une.

partial_failure

Ce champ doit être défini sur true lors de l'importation des conversions. Suivez les consignes concernant les échecs partiels lorsque vous traitez la réponse.

Importer la demande

Une fois que vous avez renseigné vos objets ClickConversion et construit votre requête, vous pouvez envoyer votre importation.

Java

// Creates the conversion upload service client.
try (ConversionUploadServiceClient conversionUploadServiceClient =
    googleAdsClient.getLatestVersion().createConversionUploadServiceClient()) {
  // Uploads the click conversion. Partial failure should always be set to true.

  // NOTE: This request contains a single conversion as a demonstration.  However, if you have
  // multiple conversions to upload, it's best to upload multiple conversions per request
  // instead of sending a separate request per conversion. See the following for per-request
  // limits:
  // https://developers.google.com/google-ads/api/docs/best-practices/quotas#conversion_upload_service
  UploadClickConversionsResponse response =
      conversionUploadServiceClient.uploadClickConversions(
          UploadClickConversionsRequest.newBuilder()
              .setCustomerId(Long.toString(customerId))
              .addConversions(clickConversion)
              // Enables partial failure (must be true).
              .setPartialFailure(true)
              .build());
      

C#

// Uploads the click conversion. Partial failure should always be set to true.
// NOTE: This request contains a single conversion as a demonstration.
// However, if you have multiple conversions to upload, it's best to upload multiple
// conversions per request instead of sending a separate request per conversion.
// See the following for per-request limits:
// https://developers.google.com/google-ads/api/docs/best-practices/quotas#conversion_upload
UploadClickConversionsResponse response =
    conversionUploadService.UploadClickConversions(
        new UploadClickConversionsRequest()
        {
            CustomerId = customerId.ToString(),
            Conversions = { clickConversion },
            // Enables partial failure (must be true).
            PartialFailure = true
        });

      

PHP

// Issues a request to upload the click conversion.
$conversionUploadServiceClient = $googleAdsClient->getConversionUploadServiceClient();
// NOTE: This request contains a single conversion as a demonstration.  However, if you have
// multiple conversions to upload, it's best to upload multiple conversions per request
// instead of sending a separate request per conversion. See the following for per-request
// limits:
// https://developers.google.com/google-ads/api/docs/best-practices/quotas#conversion_upload_service
$response = $conversionUploadServiceClient->uploadClickConversions(
    // Enables partial failure (must be true).
    UploadClickConversionsRequest::build($customerId, [$clickConversion], true)
);
      

Python

# Creates the conversion upload service client.
conversion_upload_service: ConversionUploadServiceClient = (
    client.get_service("ConversionUploadService")
)
# Uploads the click conversion. 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 most efficient 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_service
response: UploadClickConversionsResponse = (
    conversion_upload_service.upload_click_conversions(
        customer_id=customer_id,
        conversions=[click_conversion],
        # Enables partial failure (must be true).
        partial_failure=True,
    )
)
      

Ruby

response = client.service.conversion_upload.upload_click_conversions(
  customer_id: customer_id,
  conversions: [click_conversion],
  # Partial failure must be true.
  partial_failure: true,
)

if response.partial_failure_error
  puts "Partial failure encountered: #{response.partial_failure_error.message}"
else
  result = response.results.first
  puts "Uploaded click conversion that happened at #{result.conversion_date_time} " \
    "to #{result.conversion_action}."
end
      

Perl

# Upload the click conversion. Partial failure should always be set to true.
#
# NOTE: This request contains a single conversion as a demonstration.
# However, if you have multiple conversions to upload, it's best to
# upload multiple conversions per request instead of sending a separate
# request per conversion. See the following for per-request limits:
# https://developers.google.com/google-ads/api/docs/best-practices/quotas#conversion_upload_service
my $response =
  $api_client->ConversionUploadService()->upload_click_conversions({
    customerId  => $customer_id,
    conversions => [$click_conversion],
    # Enable partial failure (must be true).
    partialFailure => "true"
  });
      

curl

Examiner vos importations

Utilisez le rapport de diagnostic du suivi avancé des conversions pour les prospects afin d'examiner l'état général de vos importations récentes.

Les conversions importées sont reflétées dans les rapports pour la date d'impression du clic d'origine, et non pour la date de la demande d'importation ou la date du conversion_date_time du ClickConversion.

Il faut jusqu'à trois heures pour que les statistiques sur les conversions importées s'affichent dans votre compte Google Ads pour l'attribution au dernier clic. Pour les autres modèles d'attribution de recherche, cela peut prendre plus de trois heures. Pour en savoir plus, consultez le guide sur la fraîcheur des données.

Lorsque vous créez des rapports sur les métriques de conversion de vos campagnes, consultez Mappage des métriques de l'interface utilisateur pour mettre en corrélation les métriques de l'interface utilisateur Google Ads avec les champs de rapport de l'API Google Ads. Vous pouvez également interroger la ressource conversion_action pour afficher le nombre total de conversions et la valeur de conversion totale pour une action de conversion donnée.

Bonnes pratiques

Lorsque vous implémentez le suivi avancé des conversions pour les prospects, tenez compte des bonnes pratiques suivantes.

Envoyer toutes les données de conversion, quelle que soit leur exhaustivité

Pour que les rapports sur les conversions soient complets et précis, importez tous les événements de conversion hors connexion disponibles, y compris ceux qui ne proviennent pas de Google Ads. Les conversions qui n'incluent que des données fournies par l'utilisateur restent utiles et peuvent contribuer positivement à l'optimisation des campagnes Google Ads.

Si vous attribuez un order_id à une conversion, nous vous recommandons de l'inclure. Si vous disposez du GCLID pour une conversion, nous vous recommandons de l'envoyer en plus du user_identifiers pour améliorer les performances. De plus, si vous disposez de plusieurs UserIdentifier pour la conversion, incluez-les tous dans l'objet ClickConversion pour augmenter les chances de correspondance.

Regrouper plusieurs conversions en une seule requête

Si vous avez plusieurs conversions à importer, regroupez-les dans un seul UploadClickConversionsRequest, plutôt que d'envoyer une requête d'importation par conversion.

Consultez le guide des quotas pour connaître les limites du nombre de conversions par requête.

Si vous souhaitez que les diagnostics des données hors connexion regroupent un ensemble de requêtes sous le même job logique, définissez le job_id de toutes les requêtes sur la même valeur. Cela peut être utile si vous avez un seul job ou processus qui importe un grand nombre de conversions à l'aide de plusieurs requêtes. Si vous définissez le job_id sur la même valeur pour chacune de ces requêtes, vous pouvez récupérer une seule entrée pour le job à partir de job_summaries. Si vous laissez l'API Google Ads attribuer une valeur générée par le système au job_id de chaque requête, le job_summaries contient une entrée distincte pour chaque requête, ce qui peut compliquer l'analyse de l'état global de votre job.

Ne pas utiliser de données d'attribution externes

Lorsque vous utilisez le suivi avancé des conversions pour les prospects, ne définissez pas external_attribution_data sur ClickConversion et ne spécifiez pas de conversion_action qui utilise un modèle d'attribution externe. Google Ads n'est pas compatible avec les conversions attribuées via un système externe pour les importations utilisant les données fournies par l'utilisateur.

Ne pas inclure de variables personnalisées

Lorsque vous utilisez le suivi avancé des conversions pour les prospects, n'incluez aucun custom_variables. Google Ads ne permet pas d'utiliser des variables personnalisées avec les données fournies par l'utilisateur dans les importations de conversions. Si des variables personnalisées sont incluses dans des conversions contenant des données fournies par l'utilisateur, ces conversions seront considérées comme non valides et supprimées.

Dépannage

Les diagnostics des données hors connexion constituent une ressource unique permettant d'examiner l'état général de vos importations de manière continue. Toutefois, lors de l'implémentation, vous pouvez utiliser les informations de cette section pour examiner les erreurs signalées dans le champ partial_failure_error de la réponse.

Les erreurs les plus courantes lors de l'importation d'actions de conversion sont les erreurs d'autorisation, telles que USER_PERMISSION_DENIED. Vérifiez que le numéro client de votre requête correspond au client de conversion Google Ads propriétaire de l'action de conversion. Pour en savoir plus, consultez notre guide sur l'autorisation et notre guide sur les erreurs courantes pour obtenir des conseils sur la façon de déboguer ces différentes erreurs.

Déboguer les erreurs courantes

Les conseils suivants vous aident à diagnostiquer et à corriger les erreurs courantes liées au suivi avancé des conversions pour les prospects.

Erreur
NO_CONVERSION_ACTION_FOUND

L'action de conversion spécifiée n'est pas activée ou n'est pas accessible par le compte client spécifié par le champ customer_id dans la requête. Assurez-vous que l'action de conversion de votre importation est activée et appartient au client qui envoie la demande d'importation.

Cette erreur peut également se produire si le GCLID de la requête appartient à un compte client qui n'a pas accès à l'action de conversion spécifiée dans la requête. Vous pouvez vérifier si un GCLID appartient à un compte client à l'aide de la ressource click_view, en envoyant une requête qui filtre par click_view.gclid et segments.date, où la date correspond à la date du clic.

INVALID_CONVERSION_ACTION_TYPE Le type de l'action de conversion spécifiée n'est pas valide pour le suivi avancé des conversions pour les prospects. Assurez-vous que le ConversionAction spécifié dans votre demande d'importation est de type UPLOAD_CLICKS.
CUSTOMER_NOT_ENABLED_ENHANCED_CONVERSIONS_FOR_LEADS Assurez-vous d'avoir activé le suivi avancé des conversions pour les prospects dans vos paramètres de conversion. Pour savoir comment procéder, consultez le guide des prérequis.
DUPLICATE_ORDER_ID Les événements importés incluent plusieurs conversions avec le même ID de commande et n'ont donc pas été traités. Supprimez les doublons dans les ID de commande, puis réessayez.
CLICK_NOT_FOUND Aucun clic ne correspond aux identifiants utilisateur fournis.

Si une conversion rencontre cet avertissement, l'API Google Ads l'inclut dans le successful_event_count de vos diagnostics sur les données hors connexion. L'API Google Ads inclut une entrée pour CLICK_NOT_FOUND dans la collection alerts afin que vous puissiez surveiller la fréquence de cet avertissement.

Cette erreur est attendue si le clic ne provient pas d'une campagne Google Ads. Par exemple, il peut provenir de SA360 ou de DV360. Voici d'autres causes possibles :

Dans les rares cas où le client qui importe les données est différent du client de conversion Google Ads, cette erreur peut signifier que le client qui importe les données a accepté les conditions d'utilisation des données client, mais pas le client qui diffuse les annonces.

Vous pouvez déterminer si un compte a accepté les conditions d'utilisation des données client en interrogeant la ressource customer et en vérifiant le champ customer.conversion_tracking_setting.accepted_customer_data_terms.