Chrome Extension — Marketer Setup
Before the Chrome extension can run experiments on your domain, you need to configure three things in the 10x.in backend:
- Map your domain to your handle
- Create chain rules that define what actions to trigger (popups, banners, CTA swaps)
- Create personalization rules that target specific visitor segments
All setup is done via the API.
- Step 1 (domain mapping) requires an OWNER JWT.
- Steps 2 and 3 (rules) can use PAT (
patv1_...) or JWT with write access.
Tip
If you have already mapped your domain and created experiments via the dashboard or other tooling, skip to the verification step at the end.
Prerequisites
| Requirement | How to get it |
|---|---|
| A 10x.in handle | Create one at https://app.{PUBLIC_DOMAIN} or via POST /v2/handles |
| An OWNER JWT | Sign in as account owner (required for /v2/account/domains/*) |
| A PAT token (optional for rules) | Generate from dashboard under Settings > API Tokens |
| A domain you control | You need access to its DNS records |
Set tokens as environment variables:
export OWNER_JWT="eyJ..."
export TOKEN="patv1_your_token_here" # optional for steps 2/3
export API="https://api.10x.in"
Step 1: Map your domain to your handle
This tells the platform that traffic on your domain should resolve to your handle. The Chrome extension uses the GET /v2/public/domain-lookup endpoint to detect mapped domains.
Register the domain
curl -X POST "$API/v2/account/domains" \ -H "Authorization: Bearer $OWNER_JWT" \ -H "Content-Type: application/json" \ -d '{ "domain": "acmestore.com", "sourceType": "BYOD_HOSTNAME", "defaultHandle": "acmestore" }'Response (trimmed):
{ "domain": { "domain": "acmestore.com", "status": "PENDING_DELEGATION", "statusReason": "awaiting_nameserver_delegation" }, "verification": { "txtName": "_ls-verify.acmestore.com", "txtValue": "lsv1...." } }Configure DNS
Use the domain setup values returned by the API:
- Save
verification.txtNameandverification.txtValue. - Run reconcile once and fetch
nameservers[]fromGET /v2/account/domains/{domain}. - At your registrar, set NS delegation to those nameservers.
- In delegated DNS, add TXT verification and traffic record values shown in Domain Management.
- Save
Trigger reconciliation
Trigger reconcile after DNS changes:
curl -X POST "$API/v2/account/domains/acmestore.com/reconcile" \ -H "Authorization: Bearer $OWNER_JWT"Poll
GET /v2/account/domains/acmestore.comuntil status isACTIVE.Verify the domain is active
curl "$API/v2/public/domain-lookup?domain=acmestore.com"Expected response:
{ "handle": "acmestore", "pathRules": [], "status": "ACTIVE" }If this returns
404, the domain is not yet active. CheckGET /v2/account/domains/acmestore.com.
Note
For the full registrar + DNS checklist (TXT, nameservers, status reasons), see the Custom Domains guide.
Step 2: Create chain rules
Chain rules define what action to take when a trigger event occurs. The Chrome extension prefetches chain decisions and executes matched actions.
Chain rule structure
| Field | Type | Description |
|---|---|---|
ruleId | String | Unique rule identifier |
enabled | Boolean | Whether the rule is active |
priority | Number | Lower = higher priority |
triggerEvent | String | Event that triggers evaluation (page_load, exit_intent, scroll_75, etc.) |
when | Object | Optional conditions: countryIn, deviceIn, sourceIn, campaignIn |
chainConditions | Object | Optional signal-based conditions (require/exclude) |
action | Object | What to do when the rule matches |
Action types
action.type | Required fields | What it does |
|---|---|---|
show_popup | template (HTML string) | Shows a popup overlay |
show_banner | template (HTML string) | Shows a banner at top/bottom of page |
swap_cta | selector (CSS), template or vars.text | Replaces element content |
redirect | destinationUrl | Navigates to a different URL |
fire_event | eventName | Dispatches a custom DOM event |
add_to_cart | metadata | Fires a cart event with product data |
Example: Create an exit-intent popup
curl -X PUT "$API/v2/handles/acmestore/chain-rules/exit-popup-1" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"ruleId": "exit-popup-1",
"enabled": true,
"priority": 10,
"triggerEvent": "exit_intent",
"when": {},
"chainConditions": { "require": [], "exclude": [] },
"action": {
"type": "show_popup",
"template": "<div style=\"position:fixed;top:0;left:0;width:100%;height:100%;background:rgba(0,0,0,0.5);display:flex;align-items:center;justify-content:center;z-index:99999\"><div style=\"background:white;padding:40px;border-radius:12px;text-align:center;max-width:400px\"><h2 style=\"margin:0 0 12px\">Wait! Get 10% off</h2><p style=\"color:#666;margin:0 0 20px\">Use code EXIT10 at checkout.</p><a href=\"/checkout?coupon=EXIT10\" style=\"background:#0B6B3A;color:white;padding:12px 24px;border-radius:8px;text-decoration:none;display:inline-block\">Claim Discount</a></div></div>"
}
}'
Example: Create a page-load banner
curl -X PUT "$API/v2/handles/acmestore/chain-rules/welcome-banner" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"ruleId": "welcome-banner",
"enabled": true,
"priority": 20,
"triggerEvent": "page_load",
"when": {},
"chainConditions": { "require": [], "exclude": [] },
"action": {
"type": "show_banner",
"template": "<div style=\"background:#0B6B3A;color:white;padding:12px;text-align:center;font-family:sans-serif\">Free shipping on orders over $50. <a href=\"/shop\" style=\"color:white;text-decoration:underline\">Shop now</a></div>"
}
}'
Note
For signal-based chain rules (e.g., "show popup only if user viewed 3+ products"), see the Chain Signals and Prefetch guide.
Step 3: Create personalization rules
Personalization rules let you show different content to different visitor segments based on their source, campaign, country, or device.
Personalization rule structure
| Field | Type | Description |
|---|---|---|
ruleId | String | Unique rule identifier |
enabled | Boolean | Whether the rule is active |
priority | Number | Lower = higher priority |
when | Object | Conditions: sourceIn, campaignIn, countryIn, deviceIn |
variant | Object | What to change: title, cta, destinationUrl, metadata |
Example: Country-based CTA personalization
curl -X PUT "$API/v2/handles/acmestore/personalization-rules/us-cta" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"ruleId": "us-cta",
"enabled": true,
"priority": 10,
"when": {
"countryIn": ["US"]
},
"variant": {
"id": "us-variant",
"title": "Free Shipping to the US!",
"cta": "Shop with Free US Shipping"
}
}'
Example: Campaign-specific redirect
curl -X PUT "$API/v2/handles/acmestore/personalization-rules/spring-sale" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"ruleId": "spring-sale",
"enabled": true,
"priority": 5,
"when": {
"campaignIn": ["spring-2026"]
},
"variant": {
"id": "spring-redirect",
"destinationUrl": "https://acmestore.com/spring-sale"
}
}'
Note
For detailed personalization concepts, see the Smart Link Personalization guide.
Step 4: Verify your setup
Check domain resolution
curl "$API/v2/public/domain-lookup?domain=go.acmestore.com"
Should return your handle and ACTIVE status.
Check chain decisions
curl -X POST "$API/v2/public/chain/prefetch" \
-H "Content-Type: application/json" \
-d '{
"handle": "acmestore",
"triggerEvents": ["page_load", "exit_intent", "scroll_75", "idle_30s"]
}'
You should see your rules in the decisions map with "matched": true.
Check personalization rules
curl "$API/v2/public/handles/acmestore/personalization-rules"
Should return your rules with "enabled": true.
Test with the extension
- Install and log into the extension (see Chrome Extension guide).
- Navigate to your mapped domain.
- The badge should turn green with the experiment count.
- Trigger the appropriate event (scroll, leave the page, wait 30 seconds) to see the action.
Checklist
- [ ] Domain registered and DNS CNAME configured
- [ ] Domain reconciled and status is
ACTIVE - [ ] At least one chain rule created and enabled
- [ ] Chain prefetch returns
"matched": truefor your trigger events - [ ] Extension installed, logged in, and badge is green on your domain