Zarządzanie konwersjami offline

Za pomocą interfejsu Google Ads API możesz importować do Google Ads konwersje offline, aby śledzić reklamy, które doprowadziły do sprzedaży offline, np. przez telefon lub za pośrednictwem przedstawiciela handlowego.

Aby w pełni korzystać z zalet importowania danych o konwersjach, zalecamy wdrożenie konwersji rozszerzonych dotyczących potencjalnych klientów, które wykorzystują identyfikatory kliknięcia Google i dane przekazywane przez użytkowników, aby zmaksymalizować trwałość i skuteczność.

Konwersje rozszerzone

Konwersje rozszerzone pomagają zwiększyć dokładność pomiaru konwersji, uzupełniając dane o konwersjach danymi własnymi o konwersjach, takimi jak adres e-mail, imię i nazwisko, adres pocztowy i numer telefonu.

Istnieją 2 typy konwersji rozszerzonych. Więcej informacji znajdziesz w artykule w Centrum pomocy Informacje o konwersjach rozszerzonych.

W następnej sekcji dowiesz się, jak ulepszać konwersje offline, czyli korzystać z funkcji zwanej też konwersjami rozszerzonymi dotyczącymi potencjalnych klientów.

Czym są konwersje rozszerzone dotyczące potencjalnych klientów?

Konwersje rozszerzone dotyczące potencjalnych klientów to ulepszona wersja importowania konwersji offline, która wykorzystuje dane przekazywane przez użytkowników, np. adresy e-mail, do uzupełniania importowanych danych o konwersjach offline. Dzięki temu zwiększa dokładność i skuteczność określania stawek. Gdy importujesz konwersje offline, podane zaszyfrowane dane o klientach służą do przypisywania udziału w konwersjach do kampanii Google Ads przez dopasowywanie ich do tych samych danych zebranych w Twojej witrynie, np. z formularza kontaktowego, oraz do zalogowanych klientów, którzy weszli w interakcję z Twoją reklamą. Więcej informacji o tym, jak działają konwersje rozszerzone dotyczące potencjalnych klientów, znajdziesz w tym artykule: Konwersje rozszerzone dotyczące potencjalnych klientów.

Konwersje rozszerzone dotyczące potencjalnych klientów można wdrożyć na 2 sposoby, w zależności od tego, czy do śledzenia zdarzeń przesłania formularza na stronie internetowej używasz tagu Google. Aby uzyskać najlepszą wydajność i trwałość, zdecydowanie zalecamy używanie tagu Google do konwersji rozszerzonych dotyczących potencjalnych klientów.

  • Jeśli zaczynasz od zera, zapoznaj się z sekcją Wymagania wstępne.
  • Jeśli masz już skonfigurowane importowanie konwersji offline i chcesz przejść na konwersje rozszerzone dotyczące potencjalnych klientów, zalecamy rozpoczęcie od sekcji Konfigurowanie tagowania.
  • Jeśli masz już skonfigurowany tag Google lub nie planujesz go używać i zaczynasz pracę nad integracją z interfejsem Google Ads API, przejdź do sekcji Implementacja interfejsu API.
  • Jeśli nie możesz importować danych przekazywanych przez użytkowników lub polegasz na atrybucji zewnętrznej w przypadku konwersji, zapoznaj się z przewodnikiem po starszej wersji importowania konwersji offline.

Wymagania wstępne

Najpierw wykonaj czynności opisane w naszej sekcji dla początkujących.

Aby korzystać z konwersji rozszerzonych dotyczących potencjalnych klientów, musisz włączyć tę funkcję i zaakceptować warunki dotyczące danych klientów. Możesz sprawdzić, czy te wymagania wstępne są już spełnione, wysyłając do klienta konwersji Google Ads to zapytanie:

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

Jeśli którykolwiek z tych warunków accepted_customer_data_terms lub enhanced_conversions_for_leads_enabled jest false, postępuj zgodnie z instrukcjami w Centrum pomocy, aby spełnić te wymagania wstępne.

Konfigurowanie tagowania

Skonfiguruj tag Google, aby włączyć konwersje rozszerzone dotyczące potencjalnych klientów. W tym celu postępuj zgodnie z instrukcjami w Centrum pomocy. Aby skonfigurować konwersje rozszerzone dotyczące potencjalnych klientów za pomocą Menedżera tagów Google, postępuj zgodnie z tymi instrukcjami.

Wdrażanie interfejsu API

Oto ogólny proces importowania konwersji rozszerzonych dotyczących potencjalnych klientów za pomocą interfejsu Google Ads API.

  1. Normalizuj i szyfruj dane przekazywane przez użytkowników, takie jak adres e-mail, numer telefonu i adres pocztowy.

  2. Wypełnij ClickConversionobiekty znormalizowanymi i zaszyfrowanymi danymi przekazywanymi przez użytkowników.

  3. Importuj obiekty ClickConversion do interfejsu Google Ads API za pomocą ConversionUploadService.

  4. Sprawdź importy.

Normalizowanie i szyfrowanie danych przekazywanych przez użytkowników

Ze względu na kwestie związane z ochroną prywatności przed zaimportowaniem należy zaszyfrować te dane za pomocą algorytmu SHA-256:

  • Adres e-mail
  • Numer telefonu
  • Imię
  • Nazwisko
  • Ulica i numer

Aby ustandaryzować wyniki szyfrowania, przed zaszyfrowaniem tych wartości wykonaj te czynności:

  • usuń spacje na początku i na końcu ciągu,
  • zmień pisownię tekstu na małe litery,
  • Sformatuj numery telefonów zgodnie ze standardem E.164.
  • usunąć wszystkie kropki (.) poprzedzające nazwę domeny w adresach e-mail gmail.comgooglemail.com.

Nie szyfruj tych danych:

  • Kraj
  • Region
  • Miasto
  • Kod pocztowy

Przykładowy kod

Ten przykład pokazuje, jak znormalizować i zaszyfrować dane przekazywane przez użytkowników.

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 preceding {@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 {
  String normalizedEmail = emailAddress.toLowerCase();
  String[] emailParts = normalizedEmail.split("@");
  if (emailParts.length > 1 && emailParts[1].matches("^(gmail|googlemail)\\.com\\s*")) {
    // 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("\\.", "");
    normalizedEmail = String.format("%s@%s", emailParts[0], emailParts[1]);
  }
  return normalizeAndHash(digest, normalizedEmail);
}
      

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 preceding "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 {
    $normalizedEmail = strtolower($emailAddress);
    $emailParts = explode("@", $normalizedEmail);
    if (
        count($emailParts) > 1
        && preg_match('/^(gmail|googlemail)\.com\s*/', $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]);
        $normalizedEmail = sprintf('%s@%s', $emailParts[0], $emailParts[1]);
    }
    return self::normalizeAndHash($hashAlgorithm, $normalizedEmail);
}
      

Python

def normalize_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 segments
    if len(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.
        if re.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)

    return normalize_and_hash(normalized_email)


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

Wypełnianie obiektów ClickConversion

Kolekcja obiektów ClickConversionUploadClickConversionRequest reprezentuje zestaw konwersji, które chcesz zaimportować. Podczas tworzenia obiektów ClickConversionpamiętaj o tych kwestiach:

gclid

Identyfikatory kliknięć Google to identyfikatory kliknięć, które są przechwytywane z parametrów adresu URL, gdy użytkownik kliknie Twoją reklamę i przejdzie do Twojej witryny.

user_identifiers

Jeśli korzystasz z konwersji rozszerzonych dotyczących potencjalnych klientów, musisz wypełnić pole user_identifiers znormalizowanymi i zaszyfrowanymi danymi przekazywanymi przez użytkowników. Jeśli masz kilka identyfikatorów użytkowników, utwórz osobny UserIdentifier dla każdego z nich (maksymalnie 5 identyfikatorów).

conversion_date_time

Data i godzina konwersji.

Wartość musi mieć określoną strefę czasową, a format musi być yyyy-mm-dd HH:mm:ss+|-HH:mm, np. 2022-01-01 19:32:45-05:00 (z pominięciem czasu letniego).

Strefa czasowa może mieć dowolną prawidłową wartość. Nie musi być zgodna ze strefą czasową konta. Jeśli jednak planujesz porównywać zaimportowane dane o konwersjach z danymi w interfejsie Google Ads, zalecamy używanie tej samej strefy czasowej co na koncie Google Ads, aby liczba konwersji była zgodna. Więcej szczegółów i przykładów znajdziesz w Centrum pomocy. Listę prawidłowych identyfikatorów stref czasowych znajdziesz w sekcji Kody i formaty.

conversion_action

Nazwa zasobu ConversionAction konwersji offline.

Działanie powodujące konwersję musi mieć wartość type równą UPLOAD_CLICKS i musi istnieć na koncie klienta Google Ads, na którym są rejestrowane konwersje, powiązanym z kliknięciem.

conversion_value

Wartość konwersji.

currency_code

Kod waluty conversion_value.

consent

Zdecydowanie zalecamy wypełnienie pola consent obiektu ClickConversion. Jeśli nie jest ustawiony, konwersje mogą nie być przypisywane.

order_id

Znany też jako identyfikator transakcji dla konwersji. To pole jest opcjonalne, ale zdecydowanie zalecane, ponieważ ułatwia odwoływanie się do zaimportowanych konwersji podczas wprowadzania korekt. Jeśli ustawisz go podczas importowania, musisz go używać w przypadku wszystkich korekt. Więcej informacji o używaniu identyfikatora transakcji do ograniczania liczby zduplikowanych konwersji znajdziesz w tym artykule w Centrum pomocy.

custom_variables

Wartości niestandardowych zmiennych konwersji.

Google Ads nie obsługuje niestandardowych zmiennych konwersji w połączeniu z kolumnami wbraid ani gbraid.

conversion_environment

Wskazuje środowisko, w którym zarejestrowano tę konwersję. Na przykład APP lub WEB.

session_attributes_encodedsession_attributes_key_value_pairs

Atrybuty sesji to zagregowane identyfikatory używane do atrybucji konwersji. Działają one dodatkowo do identyfikatorów kliknięć (takich jak GCLID i GBRAID) oraz danych przekazywanych przez użytkowników, które są kluczowe w przypadku konwersji rozszerzonych dotyczących potencjalnych klientów. Atrybuty sesji można importować na 2 sposoby: podając zakodowany token wygenerowany przez nasz kod JavaScript w przeglądarce lub podając poszczególne pary klucz-wartość dla każdego identyfikatora.

Aby zmaksymalizować skuteczność kampanii, zalecamy importowanie identyfikatorów kliknięć, danych przekazywanych przez użytkowników i atrybutów sesji wraz ze wszystkimi konwersjami, jeśli to możliwe.

Java

// Sets one of the sessionAttributesEncoded or sessionAttributesKeyValuePairs if either is
// provided.
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#

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.
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 = 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

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

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::V20::Services::ConversionUploadService::SessionAttributeKeyValuePair
      ->new({sessionAttributeKey => $key, sessionAttributeValue => $value});
    push @{$click_conversion->{sessionAttributesKeyValuePairs}{keyValuePairs}
    }, $pair;
  }
}
      

user_ip_address

Adres IP klienta w momencie, gdy dotarł na stronę docelową po kliknięciu reklamy i przed zdarzeniem konwersji. Jest to adres IP urządzenia klienta, a nie serwera reklamodawcy.

To pole jest ciągiem znaków reprezentującym adres IP w formacie IPv4 lub IPv6. Na przykład:

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

Przykładowy kod

Ten przykład pokazuje, jak ustawić znormalizowane i zaszyfrowane dane przekazywane przez użytkowników w obiekcie 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@example.com")
        // Phone number to be converted to E.164 format, with a leading '+' as required.
        .put("phone", "+1 800 5550102")
        // 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(normalizeAndHash(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 (.) 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' => $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::normalizeAndHash(
            $hashAlgorithm,
            $rawRecord['phone'],
            true
        )
    ]);
    // Adds the hashed email 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 = {
    # 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 = 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 = 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 = 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.
  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::V20::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::V20::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::V20::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::V20::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;
      

Ten przykład pokazuje, jak ustawić inne niezbędne pola w obiekcie 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.
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;
}

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.
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 = 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.
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 = 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.
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::V20::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::V20::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::V20::Services::ConversionUploadService::SessionAttributeKeyValuePair
      ->new({sessionAttributeKey => $key, sessionAttributeValue => $value});
    push @{$click_conversion->{sessionAttributesKeyValuePairs}{keyValuePairs}
    }, $pair;
  }
}
      

Tworzenie żądania

Po skonfigurowaniu obiektów ClickConversion i dodaniu ich do pola conversions obiektu UploadClickConversionRequest ustaw te pola i przekaż żądanie do metody UploadClickConversions w obiekcie ConversionUploadService.

customer_id
Ustaw ten parametr na klienta konwersji Google Ads na koncie, które jest źródłem kliknięć. Jeśli nie masz pewności, które konto jest właściwe, zapoznaj się z polem customer.conversion_tracking_setting.google_ads_conversion_customer w przykładzie zapytania w sekcji Wprowadzenie .
job_id

Zapewnia mechanizm kojarzenia próśb o import z informacjami o poszczególnych zadaniach w diagnostyce danych offline.

Jeśli nie ustawisz tego pola, interfejs Google Ads API przypisze do każdego żądania niepowtarzalną wartość z zakresu [2^31, 2^63). Jeśli chcesz zgrupować wiele żądań w jedno zadanie logiczne, ustaw w tym polu tę samą wartość z zakresu [0, 2^31) w każdym żądaniu w swoim zadaniu.

Symbol job_idodpowiedzi zawiera identyfikator zadania dla żądania, niezależnie od tego, czy podano wartość, czy też interfejs Google Ads API przypisał wartość.

partial_failure

Podczas importowania konwersji to pole musi mieć wartość true. Podczas przetwarzania odpowiedzi postępuj zgodnie z wskazówkami dotyczącymi częściowych błędów.

Importowanie żądania

Gdy wypełnisz obiekty ClickConversion i utworzysz żądanie, możesz przesłać import.

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 = 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 = 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"
  });
      

Sprawdzanie importów

Użyj raportu z diagnostyki konwersji rozszerzonych dotyczących potencjalnych klientów, aby sprawdzić ogólny stan ostatnich importów.

Zaimportowane konwersje są uwzględniane w raportach dotyczących daty wyświetlenia pierwotnego kliknięcia, a nie daty prośby o import ani daty conversion_date_time ClickConversion.

Statystyki zaimportowanych konwersji pojawiają się na koncie Google Ads po upływie około 3 godzin w przypadku atrybucji według ostatniego kliknięcia. W przypadku innych modeli atrybucji w wyszukiwarce może to potrwać dłużej niż 3 godziny. Więcej informacji znajdziesz w przewodniku po częstotliwości aktualizacji danych.

Podczas raportowania danych o konwersjach w kampaniach zapoznaj się z mapowaniem danych interfejsu, aby powiązać dane interfejsu Google Ads z polami raportowania interfejsu Google Ads API. Możesz też wysłać zapytanie do zasobu conversion_action, aby wyświetlić łączną liczbę konwersji i łączną wartość konwersji w przypadku danej działania powodującego konwersję.

Sprawdzone metody

Podczas wdrażania konwersji rozszerzonych w przypadku potencjalnych klientów pamiętaj o tych sprawdzonych metodach.

Wysyłanie wszystkich danych o konwersjach bez względu na ich kompletność

Aby mieć pełne i dokładne raporty o konwersjach, importuj wszystkie dostępne zdarzenia konwersji offline, w tym niepochodzące z Google Ads. Konwersje, które zawierają tylko dane przekazywane przez użytkowników, są nadal przydatne i mogą pozytywnie wpływać na optymalizację kampanii Google Ads.

Jeśli przypiszesz do konwersji order_id, zalecamy jego uwzględnienie. Jeśli masz identyfikator kliknięcia Google dla konwersji, zalecamy wysyłanie go oprócz parametru user_identifiers, aby zwiększyć skuteczność. Jeśli masz więcej niż jeden UserIdentifier dla konwersji, uwzględnij je wszystkie w obiekcie ClickConversion, aby zwiększyć prawdopodobieństwo dopasowania.

Grupowanie wielu konwersji w jednym żądaniu

Jeśli masz do zaimportowania wiele konwersji, połącz je w jedną grupęUploadClickConversionsRequest zamiast wysyłać prośbę o importowanie dla każdej konwersji.

Zapoznaj się z przewodnikiem dotyczącym limitów liczby konwersji na żądanie.

Jeśli chcesz, aby diagnostyka danych offline grupowała zestaw żądań w ramach tego samego zadania logicznego, ustaw job_id wszystkich żądań na tę samą wartość. Może to być przydatne, jeśli masz jedno zadanie lub proces, który importuje dużą liczbę konwersji za pomocą wielu żądań. Jeśli w każdym z tych żądań ustawisz parametr job_id na tę samą wartość, możesz pobrać pojedynczy wpis dotyczący zadania z job_summaries. Jeśli zamiast tego pozwolisz interfejsowi Google Ads API przypisać wygenerowaną przez system wartość do parametru job_id każdego żądania, parametr job_summaries będzie zawierać osobny wpis dla każdego żądania, co może utrudnić analizowanie ogólnego stanu zadania.

Nie używaj danych atrybucji zewnętrznej

Jeśli korzystasz z konwersji rozszerzonych dotyczących potencjalnych klientów, nie ustawiaj external_attribution_dataClickConversion ani nie określaj conversion_action, który korzysta z zewnętrznego modelu atrybucji. Google Ads nie obsługuje konwersji przypisanych zewnętrznie w przypadku importowania danych przekazywanych przez użytkowników.

Nie uwzględniaj zmiennych niestandardowych

Jeśli używasz konwersji rozszerzonych dotyczących potencjalnych klientów, nie uwzględniaj żadnych custom_variables. Google Ads nie obsługuje używania zmiennych niestandardowych z danymi przekazywanymi przez użytkowników w przypadku importowania konwersji. Jeśli zmienne niestandardowe są uwzględniane w konwersjach, które zawierają dane przekazywane przez użytkowników, takie konwersje będą uznawane za nieprawidłowe i będą odrzucane.

Rozwiązywanie problemów

Diagnostyka danych offline to jedno miejsce, w którym możesz na bieżąco sprawdzać ogólny stan importów. Podczas wdrażania możesz jednak użyć informacji w tej sekcji, aby zbadać błędy zgłoszone w polu partial_failure_error odpowiedzi.

Najczęstsze błędy podczas importowania działań powodujących konwersję to błędy autoryzacji, np. USER_PERMISSION_DENIED. Sprawdź, czy w żądaniu masz ustawiony identyfikator klienta na klienta Google Ads, który jest właścicielem działania powodującego konwersję. Więcej szczegółów znajdziesz w naszym przewodniku po autoryzacji, a wskazówki dotyczące debugowania różnych błędów znajdziesz w naszym przewodniku po najczęstszych błędach.

Debugowanie typowych błędów

Błąd
NO_CONVERSION_ACTION_FOUND

Określone działanie powodujące konwersję jest wyłączone lub klient nie ma do niego dostępu. Konto klienta jest określone w polu `client_id` w żądaniu. Upewnij się, że działanie powodujące konwersję w przesłanym pliku jest włączone i należy do klienta, który wysyła prośbę o przesłanie.

Ten błąd może też wystąpić, jeśli identyfikator GCLID w żądaniu należy do konta klienta, które nie ma dostępu do działania powodującego konwersję określonego w żądaniu. Możesz sprawdzić, czy identyfikator kliknięcia Google należy do konta klienta, korzystając z zasobu click_view. Wystarczy, że prześlesz zapytanie, które filtruje wyniki według parametrów click_view.gclidsegments.date, gdzie data to data kliknięcia.

INVALID_CONVERSION_ACTION_TYPE Określone działanie powodujące konwersję ma typ, który jest nieprawidłowy w przypadku konwersji rozszerzonych dotyczących potencjalnych klientów. Upewnij się, że ConversionAction określony w prośbie o przesłanie ma typ UPLOAD_CLICKS.
CUSTOMER_NOT_ENABLED_ENHANCED_CONVERSIONS_FOR_LEADS Upewnij się, że w ustawieniach konwersji masz włączone konwersje rozszerzone dotyczące potencjalnych klientów. Instrukcje znajdziesz w przewodniku dotyczącym wymagań wstępnych.
DUPLICATE_ORDER_ID Nie udało się przetworzyć zaimportowanych zdarzeń, ponieważ zawierają one wiele konwersji z tym samym identyfikatorem zamówienia. Upewnij się, że identyfikatory zamówień są unikalne, i spróbuj ponownie.
CLICK_NOT_FOUND Nie znaleziono kliknięcia pasującego do podanych identyfikatorów użytkownika. Interfejs Google Ads API zwraca ten błąd tylko wtedy, gdy na UploadClickConversionsRequest wartość debug_enabled to true.

Jeśli konwersja napotka to ostrzeżenie, interfejs Google Ads API uwzględni je w successful_event_count diagnostyce danych offline. Interfejs Google Ads API zawiera wpis dotyczący CLICK_NOT_FOUND w kolekcji alerts, dzięki czemu możesz monitorować częstotliwość tego ostrzeżenia.

Ten błąd jest oczekiwany, jeśli kliknięcie nie pochodzi z kampanii Google Ads. Może ona pochodzić np. z SA360 lub DV360. Inne możliwe przyczyny:

W rzadkich przypadkach, gdy klient przesyłający dane różni się od klienta konwersji w Google Ads, ten błąd może oznaczać, że klient przesyłający dane zaakceptował warunki dotyczące danych klientów, ale klient wyświetlający reklamy nie.

Aby sprawdzić, czy konto zaakceptowało warunki dotyczące danych klienta, wyślij zapytanie do zasobu customer i sprawdź pole customer.offline_conversion_tracking_info.accepted_customer_data_terms.