웹사이트 유형에 따라 트리거해야 하는 이벤트가 달라집니다. 웹사이트의 목적에 따라 관련 섹션을 참조하세요:
웹사이트에서 제공되는 “필수” 이벤트는 해당 특정 이벤트의 pixel 실패를 방지하기 위해 반드시 전달되어야 합니다. 연동을 시작하기 전에 AppLovin의 개인정보 보호 가이드라인 및 데이터 공유 요구 사항을 반드시 검토하시기 바랍니다.
page_view 이벤트사용자가 사이트의 새 페이지로 이동할 때 page_view를 트리거합니다.
사이트의 모든 페이지에서 이 이벤트를 트리거하고 선택적으로 다음 파라미터를 포함합니다:
| 이름 | 유형 | 필수 여부 | 설명 |
|---|---|---|---|
user_data | User data | false | 이벤트를 수행하는 사용자에 대한 정보 |
view_item 이벤트사용자가 특정 제품 페이지에 도달했을 때 이 이벤트를 트리거합니다. 이 이벤트를 보낼 때 다음 파라미터를 포함합니다:
| 이름 | 유형 | 필수 여부 | 설명 |
|---|---|---|---|
items | Axon item[ ] | true | 이벤트 대상 아이템 목록 |
currency | string | recommended | 통화에 대한 세 자리 ISO 4217 코드 |
user_data | User data | false | 이벤트를 수행하는 사용자에 대한 정보 |
value | number | false | 이벤트의 금전적 가치로, 각 아이템의 price × quantity 합계로 계산됨 |
add_to_cart 이벤트사용자가 장바구니에 아이템을 추가할 때 이 이벤트를 트리거합니다. 이 이벤트를 보낼 때 다음 파라미터를 포함합니다:
| 이름 | 유형 | 필수 여부 | 설명 |
|---|---|---|---|
items | Axon item[ ] | true | 이벤트 대상 아이템 목록 |
currency | string | recommended | 통화에 대한 세 자리 ISO 4217 코드 |
user_data | User data | false | 이벤트를 수행하는 사용자에 대한 정보 |
value | number | false | 장바구니에 추가된 아이템의 금전적 가치로, 각 아이템의 price × quantity 합계로 계산됨 |
begin_checkout 이벤트사용자가 결제 프로세스를 시작할 때 이 이벤트를 트리거합니다. 이 이벤트를 보낼 때 다음 파라미터를 포함합니다:
| 이름 | 유형 | 필수 여부 | 설명 |
|---|---|---|---|
currency | string | true | 통화에 대한 세 자리 ISO 4217 코드 |
items | Axon item[ ] | true | 이벤트 대상 아이템 목록 |
value | number | true | 이벤트의 금전적 가치로, 각 아이템의 price × quantity 합계로 계산됨 |
user_data | User data | false | 이벤트를 수행하는 사용자에 대한 정보 |
purchase 이벤트사용자가 구매를 완료했을 때 이 이벤트를 트리거합니다. 이 이벤트를 보낼 때 다음 파라미터를 포함합니다:
| 이름 | 유형 | 필수 여부 | 설명 |
|---|---|---|---|
currency | string | true | 통화에 대한 세 자리 ISO 4217 코드 |
is_new_customer | boolean | false | AppLovin Shopify 앱을 사용하지 않고 주문 내역 데이터를 업로드할 계획이 없는 경우에만 이 파라미터를 전달하세요. 신규 고객인 경우 true, 그렇지 않은 경우 false입니다. |
items | Axon item[ ] | true | 이벤트 대상 아이템 목록 |
shipping | number | true | 거래와 관련된 배송비. 배송비가 없는 경우 0으로 설정합니다. |
tax | number | true | 거래와 관련된 세금. 세금이 없는 경우 0으로 설정합니다. |
transaction_id | string | true | 거래의 고유 식별자 |
value | number | true | 세금 및 배송비 전의 총 청구 금액 (소계) |
user_data | User data | true | 이벤트를 수행하는 사용자에 대한 정보 |
AppLovin은 아래에 나열된 이벤트를 권장하지만, 필수 사항은 아닙니다:
add_payment_info 이벤트고객이 사이트에 결제 정보를 제출할 때 이 이벤트를 트리거합니다. 예를 들어, 사용자가 물건을 구매할 때 결제 정보를 입력하는 경우입니다. 이 이벤트를 보낼 때 다음 파라미터를 포함합니다:
| 이름 | 유형 | 필수 여부 | 설명 |
|---|---|---|---|
currency | string | recommended | 통화에 대한 세 자리 ISO 4217 코드 |
items | Axon item[ ] | recommended | 이벤트 대상 아이템 목록 |
payment_type | Payment type | recommended | 사용된 payment type |
value | number | recommended | 이벤트의 금전적 가치로, 각 아이템의 price × quantity 합계로 계산됨 |
user_data | User data | false | 이벤트를 수행하는 사용자에 대한 정보 |
generate_lead 이벤트잠재 고객이 일반적으로 양식을 제출하여 관심을 표명할 때 이 이벤트를 트리거합니다. 적격한 잠재 고객(qualified leads)에 대해서만 generate_lead를 트리거하고, 중복 제출이나 품질이 낮은 잠재 고객과 같이 부적격한 잠재 고객에 대해서는 이벤트를 전송하지 마세요.
이 이벤트를 보낼 때 다음 파라미터를 포함합니다:
| 이름 | 유형 | 필수 여부 | 설명 |
|---|---|---|---|
currency | string | true | 통화에 대한 세 자리 ISO 4217 코드 |
value | number | true | 이 잠재 고객이 비즈니스에 대해 가지는 금전적 가치입니다. 적격한 잠재 고객에 대해서만 generate_lead를 전송하고, 중복 제출이나 품질이 낮은 잠재 고객과 같이 부적격한 잠재 고객에 대해서는 이벤트를 전송하지 마세요. |
user_data | User data | false | 이벤트를 수행하는 사용자에 대한 정보 |
login 이벤트사용자가 사이트의 계정에 로그인할 때 이 이벤트를 트리거합니다. 이 이벤트를 보낼 때 다음 파라미터를 포함합니다:
| 이름 | 유형 | 필수 여부 | 설명 |
|---|---|---|---|
user_data | User data | false | 이벤트를 수행하는 사용자에 대한 정보 |
sign_up 이벤트사용자가 사이트에서 계정을 등록할 때 이 이벤트를 트리거합니다. 예를 들어, 사용자가 이메일이나 소셜 미디어 로그인을 사용하여 새 계정을 등록하는 경우입니다. 이 이벤트를 보낼 때 다음 파라미터를 포함합니다:
| 이름 | 유형 | 필수 여부 | 설명 |
|---|---|---|---|
method | string | recommended | 가입에 사용된 방법 |
user_data | User data | true | 이벤트를 수행하는 사용자에 대한 정보 |
search 이벤트사용자가 검색창을 사용하여 사이트에서 콘텐츠를 검색할 때 이 이벤트를 트리거합니다. 이 이벤트를 보낼 때 다음 파라미터를 포함합니다:
| 이름 | 유형 | 필수 여부 | 설명 |
|---|---|---|---|
search_term | string | true | 사용자가 검색한 검색어 |
results | Axon item[ ] | recommended | 이벤트 대상 아이템 목록 |
user_data | User data | false | 이벤트를 수행하는 사용자에 대한 정보 |
subscribe 이벤트사용자가 서비스에 구독할 때 이 이벤트를 트리거합니다. 예를 들어, 사용자가 온라인 잡지와 같은 프리미엄 콘텐츠 서비스에 구독하는 경우입니다. 종종 이는 사용자가 멤버십 비용을 지불했음을 의미합니다. 이 이벤트를 보낼 때 다음 파라미터를 포함합니다:
| 이름 | 유형 | 필수 여부 | 설명 |
|---|---|---|---|
currency | string | false | 통화에 대한 세 자리 ISO 4217 코드 |
user_data | User data | false | 이벤트를 수행하는 사용자에 대한 정보 |
value | number | false | 이벤트의 금전적 가치 |
remove_from_cart 이벤트사용자가 장바구니에서 아이템을 제거할 때 이 이벤트를 트리거합니다. 이 이벤트를 보낼 때 다음 파라미터를 포함합니다:
| 이름 | 유형 | 필수 여부 | 설명 |
|---|---|---|---|
items | Axon item[ ] | true | 이벤트 대상 아이템 목록 |
currency | string | recommended | 통화에 대한 세 자리 ISO 4217 코드 |
user_data | User data | false | 이벤트를 수행하는 사용자에 대한 정보 |
value | number | false | 이벤트의 금전적 가치로, 각 아이템의 price × quantity 합계로 계산됨 |
view_cart 이벤트사용자가 장바구니를 볼 때 이 이벤트를 트리거합니다. 이 이벤트를 보낼 때 다음 파라미터를 포함합니다:
| 이름 | 유형 | 필수 여부 | 설명 |
|---|---|---|---|
items | Axon item[ ] | true | 이벤트 대상 아이템 목록 |
currency | string | recommended | 통화에 대한 세 자리 ISO 4217 코드 |
value | number | recommended | 이벤트의 금전적 가치로, 각 아이템의 price × quantity 합계로 계산됨 |
user_data | User data | false | 이벤트를 수행하는 사용자에 대한 정보 |
page_view 이벤트사용자가 사이트의 새 페이지로 이동할 때 page_view를 트리거합니다.
사이트의 모든 페이지에서 이 이벤트를 트리거하고 선택적으로 다음 파라미터를 포함합니다:
| 이름 | 유형 | 필수 여부 | 설명 |
|---|---|---|---|
user_data | User data | false | 이벤트를 수행하는 사용자에 대한 정보 |
generate_lead 이벤트잠재 고객이 일반적으로 양식을 제출하여 관심을 표명할 때 이 이벤트를 트리거합니다. 예를 들어, 사용자가 제품에 대한 자세한 정보를 받기 위해 문의 양식을 제출하는 경우입니다. 이 이벤트를 보낼 때 다음 파라미터를 포함합니다:
| 이름 | 유형 | 필수 여부 | 설명 |
|---|---|---|---|
currency | string | true | 통화에 대한 세 자리 ISO 4217 코드 |
value | number | true | 비즈니스에 대한 품질이나 실제 가치를 반영하는 작업의 금전적 가치입니다. 확실한 잠재 고객의 경우 더 높은 값을 전달하고, 중복 제출이나 품질이 낮은 잠재 고객의 경우 0을 전달합니다. 가치가 0인 잠재 고객은 최적화에서 제외되거나 할인될 수 있습니다. |
user_data | User data | false | 이벤트를 수행하는 사용자에 대한 정보 |
Axon item은 대부분의 이벤트에 필요한 공통 오브젝트입니다. 모든 필드 이름과 형식은 아래 표에 표시된 것과 정확히 일치해야 합니다:
| 이름 | 유형 | 필수 여부 | 설명 |
|---|---|---|---|
item_id | string | true | 아이템의 ID |
image_url | string | recommended | 아이템 이미지의 URL. 파일 확장자는 .png, .jpg 또는 .jpeg여야 합니다. |
item_category_id | number | recommended | 아이템의 카테고리 ID (아래 카테고리 ID 참조). 카테고리의 정수 ID를 보냅니다. |
item_name | string | recommended | 아이템의 이름 |
item_variant_id | string | recommended | 상위 아이템의 크기나 색상 변형과 같은 아이템 변형의 ID. 카탈로그의 모든 변형은 다른 변형이나 아이템과 공유되지 않는 고유한 item_variant_id를 가져야 합니다. |
price | number | recommended | 단일 단위에 대한 아이템 가격. 할인이 적용되는 경우 price를 할인된 단가로 설정하고 discount 파라미터를 통해 단위 할인을 지정합니다. |
quantity | number | recommended1 | 아이템 수량 |
affiliation | string | false | 제품과 관련된 특정 공급업체, 회사 또는 오프라인 매장 |
discount | number | false | 아이템에 적용된 단위 할인 |
item_brand | string | false | 아이템의 브랜드 |
1 quantity는 add_to_cart, remove_from_cart 및 purchase 이벤트에 필수입니다.
User data에는 사용자에 대한 추가 정보가 포함되어 있습니다. 사용자로부터 동의를 얻은 후에만 이 데이터를 전달해야 합니다.
| 이름 | 유형 | 필수 여부 | 설명 |
|---|---|---|---|
email | string | true | 이 사용자의 이메일 (예: “jdoe@example.com”). email은 소문자여야 합니다. pixel이 자동으로 해싱을 수행합니다. |
phone | string | true | 이 사용자의 전화번호 (예: “12223334444”). phone은 숫자만 포함해야 하며 국가 코드를 포함해야 합니다. pixel이 자동으로 해싱을 수행합니다. |
user_id | string | true | 고객의 고유 식별자. 최소 6자 이상이어야 합니다. |
AppLovin은 제공된 평문 이메일 주소와 전화번호를 해싱합니다.
emailgmail.com 및 googlemail.com에 한해, 먼저 @ 앞의 모든 마침표(.)를 제거하고, 첫 번째 더하기 기호(+)와 그 뒤의 모든 문자를 제거합니다. 도메인은 변경하지 않고 그대로 둡니다. @ 앞에 아무것도 남지 않으면 빈 값을 생성합니다.
phone1).
그 다음 SHA256을 통해 해싱합니다.
phone_last10_hashedphone을 SHA-256 해시로 보낼 때 강력히 권장됩니다.
이 값은 phone과 별개입니다. phone 해시를 이 필드에 복사하지 마세요.
이 필드를 생략해도 이벤트가 거부되지 않습니다.
평문 전화번호를 보내는 경우 이 필드를 생략하세요.
원시 전화번호에서 시작합니다. 문자가 포함되어 있으면 이 필드를 전송하지 마세요. 숫자가 아닌 모든 문자를 제거합니다. 남은 숫자가 10자리 미만이면 이 필드를 전송하지 마세요. 마지막 10자리만 유지합니다. 국가 코드를 추가하지 마세요. 그 다음 SHA256으로 해싱하고 결과를 Base64가 아닌 소문자 16진수 문자 64개로 전송합니다.
예시: +1 (415) 555-9317은 4155559317로 정규화되며, 이는 bc633bcb99fe8415d14840249611c33c26f2b3236061399774c71a80650e63c1로 해싱됩니다.
예시 (이메일 주소의 경우):
| 입력 | 정규화됨 | SHA256 |
|---|---|---|
Alice@Example.COM | alice@example.com | ff8d9819fc0e12bf0d24892e45987e249a28dce836a85cad60e28eaaa8c6d976 |
J..A.NE+work.more+extra@GMAIL.COM | jane@gmail.com | 988b074286b20c503e3015c2076533f3bf4ce5ca6f8a507ab52c2e0f98d620b7 |
Jane.Doe+Work@GoogleMail.com | janedoe@googlemail.com | 338abf9ef1c8793cadc7bcf51ed595338eb727ed9e06ce3d91d566d60b975937 |
참조 구현은 다음과 같습니다. 각 구현은 위의 두 번째 예시에 대한 해시를 출력합니다. 이를 실행하여 동일한 값이 나오는지 확인하세요.
#include <algorithm>
#include <cctype>
#include <iostream>
#include <regex>
#include <string>
#include <openssl/sha.h>
std::string normalizeAndHash(std::string email)
{
email.erase(0, email.find_first_not_of(" \t\n\r\f\v"));
email.erase(email.find_last_not_of(" \t\n\r\f\v") + 1);
std::transform(email.begin(), email.end(), email.begin(),
[](unsigned char c) { return std::tolower(c); });
static const std::regex valid("^[!-?A-~]+@[!-?A-~]+$");
if (!std::regex_match(email, valid))
return "";
const auto at = email.find('@');
std::string local = email.substr(0, at);
const std::string domain = email.substr(at + 1);
if (domain == "gmail.com" || domain == "googlemail.com")
{
local = local.substr(0, local.find('+'));
local.erase(std::remove(local.begin(), local.end(), '.'), local.end());
if (local.empty())
return "";
}
const std::string normalized = local + "@" + domain;
unsigned char hash[SHA256_DIGEST_LENGTH];
SHA256(reinterpret_cast<const unsigned char*>(normalized.data()),
normalized.size(), hash);
static constexpr char digits[] = "0123456789abcdef";
std::string out;
for (const unsigned char value : hash)
{
out += digits[value >> 4];
out += digits[value & 15];
}
return out;
}
int main()
{
std::cout << normalizeAndHash(" J..A.NE+work.more+extra@GMAIL.COM ") << "\n";
}
using System;
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;
class Program
{
static readonly Regex Valid = new Regex("^[!-?A-~]+@[!-?A-~]+$");
static string NormalizeAndHash(string email)
{
string trimmed = email.Trim(' ', '\t', '\n', '\r', '\f', '\v').ToLowerInvariant();
if (!Valid.IsMatch(trimmed))
return "";
int at = trimmed.IndexOf('@');
string local = trimmed.Substring(0, at);
string domain = trimmed.Substring(at + 1);
if (domain == "gmail.com" || domain == "googlemail.com")
local = local.Split('+')[0].Replace(".", "");
if (local.Length == 0)
return "";
using (SHA256 sha256 = SHA256.Create())
{
byte[] hash = sha256.ComputeHash(Encoding.UTF8.GetBytes(local + "@" + domain));
StringBuilder output = new StringBuilder(hash.Length * 2);
foreach (byte value in hash)
output.Append(value.ToString("x2"));
return output.ToString();
}
}
static void Main()
{
Console.WriteLine(NormalizeAndHash(" J..A.NE+work.more+extra@GMAIL.COM "));
}
}
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.HexFormat;
import java.util.regex.Pattern;
public final class EmailHash
{
private static final Pattern VALID = Pattern.compile( "^[!-?A-~]+@[!-?A-~]+$" );
static String normalizeAndHash( final String email ) throws NoSuchAlgorithmException
{
final String trimmed = email.trim().toLowerCase();
if ( !VALID.matcher( trimmed ).matches() )
{
return "";
}
final int at = trimmed.indexOf( '@' );
final String domain = trimmed.substring( at + 1 );
String local = trimmed.substring( 0, at );
if ( domain.equals( "gmail.com" ) || domain.equals( "googlemail.com" ) )
{
local = local.split( "\\+", 2 )[0].replace( ".", "" );
if ( local.isEmpty() )
{
return "";
}
}
return HexFormat.of().formatHex( MessageDigest.getInstance( "SHA-256" )
.digest( ( local + "@" + domain ).getBytes( StandardCharsets.UTF_8 ) ) );
}
public static void main( final String[] args ) throws NoSuchAlgorithmException
{
System.out.println( normalizeAndHash( " J..A.NE+work.more+extra@GMAIL.COM " ) );
}
}
import { createHash } from "crypto";
function normalizeAndHash(email) {
const trimmed = email.replace(/^[ \t\n\r\f\v]+|[ \t\n\r\f\v]+$/g, "").toLowerCase();
if (!/^[!-?A-~]+@[!-?A-~]+$/.test(trimmed)) {
return "";
}
const at = trimmed.indexOf("@");
let local = trimmed.slice(0, at);
const domain = trimmed.slice(at + 1);
if (domain === "gmail.com" || domain === "googlemail.com") {
local = local.split("+")[0].replaceAll(".", "");
}
return local ? createHash("sha256").update(`${local}@${domain}`).digest("hex") : "";
}
console.log(normalizeAndHash(" J..A.NE+work.more+extra@GMAIL.COM "));
import java.security.MessageDigest
private val VALID = Regex("^[!-?A-~]+@[!-?A-~]+$")
fun normalizeAndHash(email: String): String {
val trimmed = email.trim(' ', '\t', '\n', '\r', '\u000B', '\u000C').lowercase()
if (!VALID.matches(trimmed)) return ""
val (rawLocal, domain) = trimmed.split('@')
val local = if (domain == "gmail.com" || domain == "googlemail.com") {
rawLocal.substringBefore('+').replace(".", "").ifEmpty { return "" }
} else rawLocal
return MessageDigest.getInstance("SHA-256")
.digest("$local@$domain".toByteArray())
.joinToString("") { "%02x".format(it) }
}
fun main() {
println(normalizeAndHash(" J..A.NE+work.more+extra@GMAIL.COM "))
}
import hashlib
import re
VALID = re.compile(r"^[!-?A-~]+@[!-?A-~]+$")
def normalize_and_hash(email):
email = email.strip(" \t\n\r\f\v").lower()
if not VALID.match(email):
return ""
local, _, domain = email.partition("@")
if domain in ("gmail.com", "googlemail.com"):
local = local.split("+", 1)[0].replace(".", "")
return hashlib.sha256(f"{local}@{domain}".encode()).hexdigest() if local else ""
print(normalize_and_hash(" J..A.NE+work.more+extra@GMAIL.COM "))
import CryptoKit
import Foundation
func normalizeAndHash(_ email: String) -> String {
let trimmed = email.trimmingCharacters(
in: CharacterSet(charactersIn: " \t\n\r\u{0b}\u{0c}")).lowercased()
guard trimmed.range(of: "^[!-?A-~]+@[!-?A-~]+$", options: .regularExpression) != nil
else { return "" }
let parts = trimmed.split(separator: "@")
let domain = String(parts[1])
var local = String(parts[0])
if domain == "gmail.com" || domain == "googlemail.com" {
local = local.prefix { $0 != "+" }.filter { $0 != "." }
}
guard !local.isEmpty else { return "" }
return SHA256.hash(data: Data("\(local)@\(domain)".utf8))
.map { String(format: "%02x", $0) }.joined()
}
print(normalizeAndHash(" J..A.NE+work.more+extra@GMAIL.COM "))
988b074286b20c503e3015c2076533f3bf4ce5ca6f8a507ab52c2e0f98d620b7
아이템은 수천 개의 가능한 카테고리 중 하나에 속할 수 있습니다.
item_category_id를 선택한 카테고리에 해당하는 ID 번호로 설정합니다.
다음 목록에는 전체 카테고리 세트와 해당 ID 번호(괄호 안)가 포함되어 있습니다:
지원되는 결제 수단은 다음과 같습니다:
| 이름 | 설명 |
|---|---|
credit_card | 저장되었거나 수동으로 입력한 신용카드 |
deferred | 나중에 결제를 수집할 계획인 경우의 후불 결제 |
redeemable | 기프트 카드나 매장 크레딧과 같이 사용할 수 있는 결제 수단 |
payment_on_delivery | 배송 시 수금되는 결제 |
wallet | PayPal, Google Pay, Apple Pay 등과 같은 통합 전자지갑 |
other | 위에 정의되지 않은 다른 유형의 결제 |