URL 라우팅
사용자가 브랜드 페이지 URL로 이동하면 애플리케이션은 경로에서 urlSlug을 추출하여 광고 게재 API로 전송합니다.
URL 구조: <https://{your-domain}/{prefix}/{urlSlug}>
| 세그먼트 | 출처 | 예시 |
|---|---|---|
your-domain | 귀사의 사이트 | www.retailer.com |
prefix | 온보딩 중에 설정되는 항목들(예: 브랜드, 페이지) | brands |
urlSlug | 런타임에 URL 경로에서 | adidas |
예시
사용자가 방문하면: <https://www.retailer.com/brands/adidas:>
- 애플리케이션이
/brands/*경로와 일치합니다. adidas을 urlSlug로 추출합니다.- 할당된 광고 호스트와
"urlSlug": "adidas"및catalogId에 대해POST /ads/v3/brand-pages전화를 걸어 주십시오. - 반환된 콘텐츠 모듈을 페이지에 렌더링합니다.
슬러그 검증 규칙
브랜드는 다음 제약 조건에 따라 슬러그를 생성합니다:
- Characters: Lowercase letters (a–z), numbers (0–9), hyphens (-), and underscores (_).
- Length: Minimum 3 characters, maximum 100 characters.
- Uniqueness: Must be unique within the retailer’s catalog (
catalogId).
현재로서는 슬러그의 고유성이 캠페인 날짜 범위를 고려하지 않습니다.
- Immutability: Cannot be changed after the brand page campaign is live.
- Format: No leading or trailing hyphens (for example,
-adidasoradidas-are not allowed).
캐싱
- 광고‑제공 API의 응답을 캐시하지 마십시오. 항상 Epsilon API로 직접 요청을 보내 다음을 보장하십시오:
- 올바른 브랜드 페이지 캠페인이 제공됩니다(캠페인은 일시 중지, 업데이트 또는 교체될 수 있습니다).
- 추적 URL에는 정확한 기여 분석을 위한 요청별 새로운 식별자가 포함됩니다.
- 노출 횟수는 정확하게 유지되며 오래된 캐시된 응답의 영향을 받지 않습니다.
SEO 고려 사항: 소매업체는 브랜드 페이지가 검색 엔진에 색인될 수 있도록 허용할 수 있습니다. 브랜드 페이지 콘텐츠를 색인하면 페이지의 모든 텍스트가 검색 엔진에 노출될 수 있으므로 자연 검색 노출도가 향상될 수 있습니다.
리버스 프록시 설정
왜 리버스 프록시가 필요한지 알아보십시오.
문제점: 광고 차단기 및 개인 정보 보호 도구는 광고 도메인으로 직접 전송되는 추적 요청을 자주 차단합니다.
솔루션: 모든 추적 요청을 자신의 도메인을 통해 라우팅하여 퍼스트‑파티 트래픽으로 표시되도록 하십시오.
❌ Blocked: user-browser → [third-party-tracking-domain]
✅ Works: user-browser → yoursite.com/[custom-path] → [third-party-tracking-domain][third-party-tracking-domain]온보딩 시 제공된 실제 Epsilon 추적 엔드포인트로 대체하십시오.[custom-path]을(를) 중립적이고 고유한 경로(예:/media-proxy,/assets-endpoint또는 광고가 아닌 용어)로 대체하십시오.
A reverse proxy is required for C2S (browser) tracking. It does not apply to S2S calls, which must be sent directly to the Epsilon tracking host (see Tracking – Server-to-Server (S2S)).
구성
Your site must host a reverse proxy under a path such as https://www.retailer.com/{proxyPath}/. Browser (C2S) tracking requests to your domain on that path are forwarded to your regional tracking host (see Ad Serving API). Server-to-server tracking must not use this proxy.
행동:
- 다음 조건의 요청 수락
/epsilon/ - Forward to
https://[region]-tracking.rmn.dotomi.com/(see Ad Serving API for[region]) - 파일 경로 접미사를 보존하십시오
- 필수 HTTP 헤더 전달
- HTTPS를 강제 적용 (TLS 1.2+)
필수 헤더
| 헤더 | 설명 |
|---|---|
RP-Host | 호스트네임이 추적 요청을 수신하고 있습니다. |
X-Forwarded-For | 실제 클라이언트 IP 주소. |
X-Forwarded-Request-Path | 프록시 접두사 경로 (예: /epsilon). |
Referer | 픽셀이 실행된 페이지. |
Apache 예제
LoadModule ssl_module modules/mod_ssl.so
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_http_module modules/mod_proxy_http.so
SSLProxyEngine on
RequestHeader add "X-Forwarded-Request-Path" "/epsilon"
RequestHeader add "RP-Host" "%{HTTP_HOST}s"
RequestHeader add "Referer" "%{HTTP_REFERER}s"
ProxyPass "/epsilon" "https://[region]-tracking.rmn.dotomi.com"
ProxyPassReverse "/epsilon" "https://[region]-tracking.rmn.dotomi.com/"NGINX 예제
server {
server_name www.retailer.com;
location /epsilon/ {
proxy_ssl_server_name on;
rewrite ^/epsilon/(.*) /$1 break;
proxy_pass https://[region]-tracking.rmn.dotomi.com;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Server $server_name;
proxy_set_header RP-Host $host;
proxy_set_header X-Forwarded-Request-Path "/epsilon";
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Referer $http_referer;
}
}광고 게재 API
Epsilon serves brand pages from RMN hosts on *.rmn.dotomi.com. Substitute [region] with the segment Epsilon assigns for your deployment.
The ads API uses https://[region]-ads.rmn.dotomi.com; while tracking endpoints (impression pixels, click redirects, and S2S notification URLs) uses https://[region]-tracking.rmn.dotomi.com with the same [region] value.
In some setups, the base hostnames ads.rmn.dotomi.com and tracking.rmn.dotomi.com may be used. Epsilon will confirm the appropriate hostnames for your environment.
엔드포인트
POST https://[region]-ads.rmn.dotomi.com/ads/v3/brand-pages
Content-Type: application/json
Authorization: Basic <existing_api_key>
요청 페이로드
{
"id": "req-adidas-12345",
"catalogId": "test-catalog-adidas",
"urlSlug": "adidas",
"site": {
"domain": "www.retailer.com",
"page": "https://www.retailer.com/brand/adidas",
"ref": "https://www.retailer.com/search?q=shoes"
},
"device": {
"ua": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 ...",
"ip": "192.168.1.100",
"language": "en-US",
"devicetype": 2,
"os": "macOS",
"geo": {
"country": "USA",
"region": "CA",
"city": "San Francisco",
"zip": "94105"
}
},
"user": {
"sessionId": "sess-abc123xyz",
"customerId": "cust-789012",
"dtmId": "dtm-456def"
},
"regs": {
"gdpr": 1,
"consent": "COwJqZAOwJqZAOAAAAENAXCAAAAAAAAAAAAAABpoAIAAAEpgAIAAAg1AAAICAIAAAEA"
}
}
The regs values above illustrate the GDPR-applicable traffic:gdpr is 1, and consentis a synthetic IAB TCF v2 consent string (correct shape and charset only).
프로덕션 환경에서:
- 지리적 및 법적 규칙에 따라
gdpr을 설정하십시오. - CMP에서 라이브 TC 문자열을 전달하십시오(예:
_ _tcfapigetTCData→tcString).
비 GDPR 요청은 "gdpr": 0을 사용하고 consent을 생략하거나 ""를 사용하십시오.
iabConsentString on tracking events: Every populated tracker slot (trackers.impression, trackers.click, trackers.addToCart) includes params.iabConsentString. When you provide regs.consent on the request, this value is the literal TC string.
When you omitted regs.consent, this value is the {TCF} macro placeholder - substitute the current TCF v2 string from your CMP (for example via __tcfapi getTCData → tcString) at fire time before sending any tracking request.
요청 API 필드 정의
| 필드 | 유형 | 필수 입력 항목입니다 | 설명 |
|---|---|---|---|
id | 문자열 | 예 | 고유 요청 식별자(소매업체에서 생성) |
catalogId | 문자열 | 예 | 소매업체의 제품 카탈로그 ID(Epsilon 제공) |
urlSlug | 문자열 | 예 | 브랜드 페이지 URL 슬러그(예: 아디다스) |
| 사이트 | |||
site.domain | 문자열 | 예 | 소매업체 웹사이트 도메인 |
site.page | 문자열 | 아니요 | 브랜드 페이지가 렌더링되는 전체 URL |
site.ref | 문자열 | 아니요 | 추천 URL(사용자가 이동한 출처) |
| 장치 | |||
device.ua | 문자열 | 예 | 사용자 에이전트 문자열 |
device.ip | 문자열 | 아니요 | 클라이언트 IP 주소 |
device.language | 문자열 | 아니요 | 브라우저 언어(예: en-US) |
device.devicetype | 정수형 | 아니요 | 1=모바일, 2=PC, 4=휴대폰, 5=태블릿 |
device.os | 문자열 | 아니요 | 운영 체제 |
device.geo.country | 문자열 | 아니요 | ISO 3166-1 알파-3 국가 코드(예: USA, GBR) |
device.geo.region | 문자열 | 아니요 | 주 또는 지역 |
device.geo.city | 문자열 | 아니요 | 도시 |
device.geo.zip | 문자열 | 아니요 | 우편번호/ZIP 코드 |
| 사용자 | |||
user.sessionId | 문자열 | 아니요 | 소매업체 세션 식별자(비 PII) |
user.customerId | 문자열 | 아니요 | 소매업체 고객 식별자(비 PII) |
user.dtmId | 문자열 | 아니요 | 추적 식별자 |
| regs | |||
regs.gdpr | 정수형 | 아니요 | 0 = GDPR does not apply, 1 = GDPR applies (per OpenRTB-style signaling) |
regs.consent | 문자열 | 아니요 | IAB TCF v2 consent string (tcString from the CMP). Use only when gdpr is 1 and you have a valid string; otherwise omit or"" |
중요The JSON below is a representative and fairly complete example. Live responses are often sparser for
contentDatamodules. Do not generate fixed structures that assume every key shown here is always present for everycontentTypeor brand page.
Thethemeis different: on a successful response, it is always present and uses the nested structure described in the Theme Object section (colorsandbuttonsfully populated - required hex6 strings for every path; nonullsinsidetheme).
응답 페이로드
{
"realizedAdId": "brandpage_djogXfHSYGZOZnnkzEKunWvdNYEKABIAGgwIwIPjzAYQ3byasAE=",
"brandPageTemplateId": "6e9690ef-81d1-4fad-b2ce-749e22cceb10",
"catalogId": "test-catalog-adidas",
"urlSlug": "adidas",
"theme": {
"colors": {
"background": "#F5F5F5",
"text": {
"heading": "#1a1a1a",
"subheading": "#333333",
"body": "#5f6368",
"caption": "#9aa0a6",
"link": "#1a73e8",
"tagline": "#5f6368",
"lines": "#e0e0e0"
}
},
"buttons": {
"primary": {
"background": "#ff6600",
"text": "#FFFFFF"
},
"secondary": {
"background": "#FFFFFF",
"text": "#ff6600"
}
}
},
"trackers": {
"impression": {
"type": "impression",
"params": { "ts": "{TS}", "iabConsentString": "{TCF}" }
}
},
"trackingTypes": {
"impression": ["client.impressionPixelUrls", "server.impressionEvent"],
"productClick": ["client.clickRedirect", "client.clickEvent", "server.clickEvent"],
"productAddToCart": ["client.addToCartEvent", "server.addToCartEvent"],
"link": ["client.clickRedirect", "client.clickEvent", "server.clickEvent"],
"interaction": ["client.clickEvent", "server.clickEvent"]
},
"trackingTemplates": {
"client": {
"clickRedirect": "/tracking/v3/click/redirect/brandpage_djog...?catalogId=test-catalog-adidas&...",
"clickEvent": "/tracking/v3/event/click/brandpage_djog...?catalogId=test-catalog-adidas&...",
"addToCartEvent": "/tracking/v3/event/add-to-cart/brandpage_djog...?catalogId=test-catalog-adidas&...",
"impressionPixelUrls": [
"/tracking/v3/impression/pixel/brandpage_djog...?catalogId=test-catalog-adidas&..."
]
},
"server": {
"clickEvent": "https://[region]-tracking.rmn.dotomi.com/tracking/v3/event/click/brandpage_djog...?...",
"addToCartEvent": "https://[region]-tracking.rmn.dotomi.com/tracking/v3/event/add-to-cart/brandpage_djog...?...",
"impressionEvent": "https://[region]-tracking.rmn.dotomi.com/tracking/v3/event/impression/brandpage_djog...?..."
}
},
"contentData": [
{
"id": "hero-1",
"brandPageModuleTemplateId": "hero-template-1",
"contentType": "HERO",
"order": 1,
"tags": ["header"],
"mediaUrl": "https://example.com/images/adidas-hero.jpg",
"headline": "Impossible Is Nothing",
"subheadline": "Spring Collection",
"ctaText": "Explore",
"ctaLink": "https://example.com/adidas/explore",
"trackers": {
"click": {
"type": "link",
"params": {
"modId": "hero-1",
"rurl": "https%3A%2F%2Fexample.com%2Fadidas%2Fexplore",
"ts": "{TS}",
"iabConsentString": "{TCF}"
}
}
}
},
{
"id": "text-1",
"brandPageModuleTemplateId": "text-template-1",
"contentType": "TEXT",
"order": 2,
"text": "Discover the latest Adidas collection featuring innovative designs and sustainable materials."
// (No trackers for TEXT module, as it has no interactive elements)
}
]
}
응답 필드 정의
| 필드 | 유형 | 설명 |
|---|---|---|
realizedAdId | 문자열 | 이 브랜드 페이지 제공을 위한 고유 광고 식별자. 모든 추적 템플릿 경로에 사용됩니다. |
brandPageTemplateId | 문자열 | 이 브랜드 페이지에 사용된 템플릿 ID |
catalogId | 문자열 | 소매업체 카탈로그 ID(요청에서 전달됨) |
urlSlug | 문자열 | 브랜드 페이지 URL 슬러그(요청에서 반환된 값) |
theme | 개체 | Always present on success. Page-level styling from the brand: nested colors (background + text roles) and buttons(primary/ secondary, each with backgroundand text). See Theme Object section.The response body is returned as serialized by the ad server (no intermediate reshaping of theme) |
trackers | 개체 | Page-level tracking container. trackers.impression holds the page impression slot: type: "impression" and params including at least ts: "{TS}" and iabConsentString. |
trackingTypes | 개체 | Map of tracking type to applicable template keys. Types: impression, productClick, productAddToCart, link, interaction. Each value is an array of client.*/ server.* keys from trackingTemplates. (see How to Compose a Tracking URL). |
trackingTemplates.client | 개체 | Relative URL paths and query strings for browser (C2S) tracking - prepend your reverse-proxy base URL (BASEURL). |
trackingTemplates.server | 개체 | Absolute URL templates on the Epsilon tracking host for S2S. |
contentData[] | 배열 | 렌더링할 콘텐츠 모듈의 정렬된 배열 |
contentData[].id | 문자열 | 모듈 인스턴스 ID |
contentData[].brandPageModuleTemplateId | 문자열 | 모듈 템플릿 ID |
contentData[].contentType | 문자열 | 모듈 유형: 히어로, 텍스트, FILTER_MENU, PRODUCT_GRID, 이미지, IMAGE_GALLERY, SPLIT_LAYOUT |
contentData[].order | 정수형 | 렌더링 순서(오름차순) |
contentData[].tags | 문자열 배열 | Optional. Module tags set by the retailer in the template. Omitted entirely when no tags are set - treat missing as "no tags". Also present on nested modules within SPLIT_LAYOUT. |
contentData[].trackers | 개체 | When present, per-node tracking container. trackers.click for link/interaction/product click events; trackers.addToCart for product add-to-cart (includes {QTY} and {CONVERSION_VALUE} macros). May be omitted when there is nothing to track. |
Theme Object
Every successful Brand Page API response includes a theme object: page-level colors and button styles configured for the brand. Apply these values when rendering (for example, map them to CSS custom properties or your design tokens). The JSON is produced by the ad server and delivered as returned - there is no separate step that rewrites the theme.
Color format: Theme color values follow the platform contract from upstream (campaign/configuration): each value is a # followed by six hexadecimal digits (hex6), for example, #ff6600. Do not expect other formats (short hex3, eight-digit hex, rgb(), hsl(), or named colors). The ad server does not revalidate color format at serve time; upstream supplies hex6 for every theme field.
Structure and semantics
themecontainscolorsandbuttons- both are required wheneverthemeis present.colors.background- page or canvas background (required hex6).colors.text- seven required roles:heading,subheading,body,caption,link,tagline,lines(lines/dividers). Each value is a hex6 string.buttons.primaryandbuttons.secondary- each requiresbackgroundandtext(button fill and label colors), each a hex6 string.- Every path in the field reference table below is required. There are no optional color slots and no
nullvalues insidetheme. (Sparse or omitted fields apply elsewhere, for example incontentDatamodules.) - The
themeis page-level -all modules on the Brand Page share the same theme.
Field reference
All paths in this table are required (non-null hex6 strings).
| Path | 설명 |
|---|---|
theme.colors.background | Page/canvas background |
theme.colors.text.heading | Heading text |
theme.colors.text.subheading | Subheading text |
theme.colors.text.body | Body/paragraph text |
theme.colors.text.caption | Caption/secondary text |
theme.colors.text.link | Link text |
theme.colors.text.tagline | Tagline text |
theme.colors.text.lines | Lines and dividers |
theme.buttons.primary.background | Primary CTA button fill |
theme.buttons.primary.text | Primary CTA button label |
theme.buttons.secondary.background | Secondary button fill |
theme.buttons.secondary.text | Secondary button label |
Example - (themeobject only):
"theme": {
"colors": {
"background": "#F5F5F5",
"text": {
"heading": "#1a1a1a",
"subheading": "#333333",
"body": "#5f6368",
"caption": "#9aa0a6",
"link": "#1a73e8",
"tagline": "#5f6368",
"lines": "#e0e0e0"
}
},
"buttons": {
"primary": {
"background": "#ff6600",
"text": "#FFFFFF"
},
"secondary": {
"background": "#FFFFFF",
"text": "#ff6600"
}
}
}노드별 params(일반 키)
params(일반 키)| 매개변수 | 사용 시 | 설명 |
|---|---|---|
modId | 가장 상호작용이 많은 노드 | 콘텐츠 모듈 또는 행 식별자. |
rurl | link / productClickwhen a redirect is needed | URL-encoded destination |
ts | 대부분의 이벤트 | Cache-busting timestamp; substitute "{TS}"at fire time. |
iabConsentString | All tracker slots | Literal TC string, or {TCF} macro to substitute at fire time |
productCode | productClick / productAddToCart | 제품광고 식별자. |
sellerId | productClick / productAddToCart (marketplace) | 판매자 식별자. |
qty | productAddToCart | Absolute quantity of this SKU in the cart at the time the event fires (not a delta). Substitute {QTY} macro at fire time |
conVal | productAddToCart | Absolute monetary value of those items: quantity × unit price, minus any applied discounts. Substitute {CONVERSION_VALUE} macro at fire time |
Template-dependent fields in contentData
contentDataAside from core discriminators on each module (id, brandPageModuleTemplateId, contentType, order), property presence is not uniform across Brand Pages. Prefer feature detection - check each property before use - rather than treating every field in examples as mandatory.
The API may represent "no value" in several ways:
| Pattern | 의미 | Suggested handling |
|---|---|---|
| Key omitted | Property absent from the JSON object | Treat as absent; use optional chaining/defaults |
Explicit null | Property present with null value | Same as omitted, unless your serializer distinguishes them |
| Empty string | "" for text or URL-like fields | Usually hide or skip rendering that slice of UI |
공통 모듈 유형의 예시
제품 그리드:
Each product row includes a product object (catalogId, productCode, sellerId), an order value, and trackers when the row is trackable. Product rows provide both a click slot (type: "productClick") and an addToCartslot (type: "productAddToCart") when the SKU is attributable.
{
"product": {
"catalogId": "550e8400-e29b-41d4-a716-446655440001",
"productCode": "9221200653341",
"sellerId": "2ae0aab9-44ce-40a0-b2b9-ae61681ad224"
},
"order": 1,
"trackers": {
"click": {
"type": "productClick",
"params": {
"modId": "grid-1",
"productCode": "9221200653341",
"sellerId": "2ae0aab9-44ce-40a0-b2b9-ae61681ad224",
"rurl": "{RURL}",
"ts": "{TS}",
"iabConsentString": "{TCF}"
}
},
"addToCart": {
"type": "productAddToCart",
"params": {
"modId": "grid-1",
"productCode": "9221200653341",
"sellerId": "2ae0aab9-44ce-40a0-b2b9-ae61681ad224",
"rurl": "{RURL}",
"ts": "{TS}",
"qty": "{QTY}",
"conVal": "{CONVERSION_VALUE}",
"iabConsentString": "{TCF}"
}
}
}
}
히어로:
Headline, subheadline, CTA text and link, image, overlay, and trackers.click for the CTA when present.
{
"contentType": "HERO",
"tags": [
"header"
],
"mediaUrl": "https://example.com/images/adidas-hero.jpg",
"headline": "Impossible Is Nothing",
"subheadline": "Spring Collection",
"ctaText": "Explore",
"ctaLink": "https://example.com/adidas/explore",
"trackers": {
"click": {
"type": "link",
"params": {
"modId": "hero-1",
"rurl": "https%3A%2F%2Fexample.com%2Fadidas%2Fexplore",
"ts": "{TS}",
"iabConsentString": "{TCF}"
}
}
}
}
이미지 갤러리:
An array of images, each with a URL, alt text, and caption. trackers.click for an image only when that image links out.
{
"contentType": "IMAGE_GALLERY",
"galleryImages": [
{
"url": "https://example.com/images/recipe-spaghetti-bolognese.jpg",
"alt": "Spaghetti Bolognese",
"caption": "Spaghetti Bolognese",
"trackers": {
"click": {
"type": "link",
"params": {
"modId": "gallery-1",
"rurl": "https%3A%2F%2Fexample.com%2Frecipes%2Fspaghetti",
"ts": "{TS}",
"iabConsentString": "{TCF}"
}
}
}
}
]
}
텍스트:
Headline and body text, with no trackersunless a link is present on a line.
{
"contentType": "TEXT",
"text": "Explore our newest arrivals designed for comfort, style, and performance."
}
이미지:
Includes an image URL, caption, alt text, optional link and trackers.click details when the image is clickable
{
"contentType": "IMAGE",
"imageUrl": "https://example.com/images/model.jpg",
"caption": "New arrivals now available",
"alt": "Model wearing summer collection",
"trackers": { "click": { "type": "link", "params": { "modId": "image-1", "rurl": "https%3A%2F%2Fexample.com%2Fnew-arrivals", "ts": "{TS}", "iabConsentString": "{TCF}"
}
}

