> ## Documentation Index
> Fetch the complete documentation index at: https://docs.datalyr.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Cross-Domain Tracking

> Track users across multiple domains and subdomains

Cross-domain tracking enables DATALYR to follow users as they navigate between different domains and subdomains, maintaining attribution and user identity throughout their journey.

## What is Cross-Domain Tracking

Cross-domain tracking links user sessions and attribution data across:

* **Multiple domains** (example.com → shop.example.com)
* **Subdomains** ([www.example.com](http://www.example.com) → app.example.com → blog.example.com)
* **Third-party checkout** (yoursite.com → checkout.stripe.com → yoursite.com)
* **Payment processors** (yoursite.com → paypal.com → yoursite.com)

## How It Works

### Cross-Subdomain Tracking (Automatic)

DATALYR automatically tracks visitors across subdomains using root domain cookies.

**Example: [www.example.com](http://www.example.com) → app.example.com**

**Step 1: First Visit ([www.example.com](http://www.example.com))**

```javascript theme={null}
// User visits www.example.com
// DATALYR generates: anon_abc123
// Sets cookie: __dl_visitor_id=anon_abc123; domain=.example.com
```

**Step 2: Navigate to Subdomain (app.example.com)**

```javascript theme={null}
// User clicks link to app.example.com
// DATALYR reads cookie from .example.com
// Uses same ID: anon_abc123
// Journey continues seamlessly
```

**Result:** Same visitor ID across all subdomains, complete journey tracking.

### Root Domain Cookie

DATALYR sets visitor ID cookie on the **root domain** (e.g., `.example.com`):

**Cookie Attributes:**

```
__dl_visitor_id=anon_f47ac10b-58cc-4372-a567-0e02b2c3d479;
domain=.example.com;
path=/;
max-age=31536000;
SameSite=Lax;
Secure
```

**Accessible On:**

* `example.com`
* `www.example.com`
* `app.example.com`
* `blog.example.com`
* `shop.example.com`
* Any subdomain of `example.com`

**Not Accessible On:**

* `different-domain.com` (different root domain)
* `example.org` (different TLD)

## Supported Domain Types

### Standard TLDs

**Format:** `domain.tld`

**Examples:**

* `example.com` → Cookie: `.example.com`
* `myshop.net` → Cookie: `.myshop.net`
* `startup.io` → Cookie: `.startup.io`

**Subdomains Tracked:**

* `www.example.com`
* `app.example.com`
* `api.example.com`

### Country-Specific TLDs

**Format:** `domain.co.tld` or `domain.com.tld`

**Supported Two-Part TLDs:**

* `.co.uk` (United Kingdom)
* `.com.au` (Australia)
* `.co.nz` (New Zealand)
* `.co.jp` (Japan)
* `.co.in` (India)
* `.co.za` (South Africa)

**Examples:**

* `example.co.uk` → Cookie: `.example.co.uk`
* `myshop.com.au` → Cookie: `.myshop.com.au`

**Subdomains Tracked:**

* `www.example.co.uk`
* `shop.example.co.uk`
* `blog.example.co.uk`

### Localhost and IP Addresses

**Localhost:**

```
localhost → Cookie: localhost
```

**IPv4:**

```
192.168.1.1 → Cookie: 192.168.1.1
```

**IPv6:**

```
[::1] → Cookie: [::1]
```

## Cross-Domain Tracking (Multiple Domains)

When users navigate between **different domains** (not just subdomains), you need to pass visitor ID in the URL.

### URL Parameter Method

DATALYR automatically **reads** the `_dl_vid` parameter from URLs on page load. However, you need to **manually append** the parameter to links when navigating to different domains.

**How it works:**

1. You append `_dl_vid` to outbound links (manual step)
2. DATALYR automatically reads `_dl_vid` on the destination page (automatic)
3. The visitor ID is preserved across domains

**Manual Linking (Required):**

```javascript theme={null}
// Get visitor ID
const visitorId = datalyr.getAnonymousId();

// Append to checkout URL
const checkoutUrl = `https://checkout.example.com?_dl_vid=${visitorId}`;

// Redirect
window.location.href = checkoutUrl;
```

**On Destination Domain:**

```javascript theme={null}
// DATALYR automatically reads _dl_vid from URL on page load
// The visitor ID from the URL is used and stored in cookies/localStorage
// Journey continues seamlessly with the same visitor ID
```

### Use Cases

**E-commerce with Third-Party Checkout:**

```
yourstore.com → shopify.com/checkout → yourstore.com/thank-you
```

**Payment Processors:**

```
yoursite.com → stripe.com/checkout → yoursite.com/success
yoursite.com → paypal.com/checkout → yoursite.com/success
```

**Multi-Site Funnels:**

```
landing-page.com → signup.example.com → app.example.com
```

**Affiliate Networks:**

```
affiliate-site.com → your-offer.com
```

## Implementation Examples

### Cross-Subdomain Setup (Automatic)

No additional setup required. DATALYR automatically tracks across subdomains.

**Install on Each Subdomain:**

**[www.example.com](http://www.example.com):**

```html theme={null}
<script defer src="https://track.datalyr.com/dl.js" data-workspace-id="ws_123"></script>
```

**app.example.com:**

```html theme={null}
<script defer src="https://track.datalyr.com/dl.js" data-workspace-id="ws_123"></script>
```

**shop.example.com:**

```html theme={null}
<script defer src="https://track.datalyr.com/dl.js" data-workspace-id="ws_123"></script>
```

**Result:** Visitor ID shared automatically via `.example.com` cookie.

### Cross-Domain Setup (Manual)

Pass visitor ID between different domains:

**Source Domain (yoursite.com):**

```javascript theme={null}
// Add visitor ID to checkout link
document.addEventListener('DOMContentLoaded', function() {
  const checkoutLinks = document.querySelectorAll('a[href*="checkout.example.com"]');

  checkoutLinks.forEach(link => {
    const visitorId = datalyr.getAnonymousId();
    const url = new URL(link.href);
    url.searchParams.set('_dl_vid', visitorId);
    link.href = url.toString();
  });
});
```

**Destination Domain (checkout.example.com):**

```html theme={null}
<!-- Install DATALYR - it automatically reads _dl_vid from URL on init -->
<script defer src="https://track.datalyr.com/dl.js" data-workspace-id="ws_123"></script>
<!-- The visitor ID from ?_dl_vid=anon_abc123 will be used automatically -->
```

**Return Domain (yoursite.com/thank-you):**

```javascript theme={null}
// Visitor ID persists via cookie on yoursite.com
// Journey is complete and tracked
```

### Form Submission to Different Domain

**Form on yoursite.com:**

```html theme={null}
<form id="checkout-form" method="POST" action="https://checkout.example.com">
  <input type="hidden" name="product_id" value="SKU123">
  <!-- Visitor ID will be added by JavaScript -->
  <button type="submit">Checkout</button>
</form>

<script>
document.getElementById('checkout-form').addEventListener('submit', function(e) {
  e.preventDefault();

  const form = e.target;
  const visitorId = datalyr.getAnonymousId();

  // Add visitor ID as hidden field
  const input = document.createElement('input');
  input.type = 'hidden';
  input.name = '_dl_vid';
  input.value = visitorId;
  form.appendChild(input);

  // Submit form
  form.submit();
});
</script>
```

**Checkout page reads visitor ID:**

```javascript theme={null}
// checkout.example.com - DATALYR automatically reads _dl_vid from URL
// Note: POST data reading requires server-side implementation
// URL parameter method is recommended for client-side tracking
```

## Attribution Across Domains

Cross-domain tracking preserves attribution data across domain boundaries.

### Example: Multi-Domain Purchase Journey

**Day 1: Landing Page (landing.example.com)**

```
User clicks Facebook ad
URL: https://landing.example.com/?utm_source=facebook&utm_medium=cpc&fbclid=IwAR123
DATALYR captures:
  - anonymous_id: anon_abc123
  - utm_source: facebook
  - utm_medium: cpc
  - fbclid: IwAR123
  - Cookie set: .example.com
```

**Day 2: Main Site ([www.example.com](http://www.example.com))**

```
User navigates to www.example.com
DATALYR reads cookie from .example.com
Same visitor ID: anon_abc123
Attribution preserved: facebook / cpc / IwAR123
```

**Day 3: App (app.example.com)**

```
User signs up on app.example.com
DATALYR identifies user:
  - anonymous_id: anon_abc123 → user_id: user_456
  - Attribution still preserved
```

**Day 7: Checkout (checkout.stripe.com)**

```
User clicks checkout button
Redirected to: checkout.stripe.com?_dl_vid=anon_abc123
Stripe processes payment
Returns to: www.example.com/thank-you?_dl_vid=anon_abc123
```

**Day 7: Thank You Page ([www.example.com](http://www.example.com))**

```
DATALYR tracks purchase event:
  - anonymous_id: anon_abc123
  - user_id: user_456
  - Attribution: facebook / cpc / IwAR123

Purchase correctly attributed to Facebook ad from Day 1!
```

## Identity Across Domains

When users identify (login/signup) on any domain, their identity links across all tracked domains.

**Example:**

**Domain 1 ([www.example.com](http://www.example.com)):**

```javascript theme={null}
// User browses anonymously
// anonymous_id: anon_abc123
```

**Domain 2 (app.example.com):**

```javascript theme={null}
// User signs up
datalyr.identify('user_456', {
  email: 'user@example.com'
});

// Links: anon_abc123 → user_456
```

**Domain 3 (shop.example.com):**

```javascript theme={null}
// User purchases
datalyr.track('purchase', {
  order_id: 'ORDER_123',
  revenue: 99.99
});

// Automatically attributed to user_456
// Includes original attribution from Domain 1
```

## Troubleshooting

### Visitor ID Changes Across Subdomains

**Symptoms:**

* Different visitor IDs on different subdomains
* Journeys not linked

**Common Causes:**

**1. Cookie Blockers**
Browser extensions or privacy tools blocking third-party cookies.

**Solution:**

```javascript theme={null}
// Check if cookies are blocked
console.log('Cookie available:', document.cookie.includes('__dl_visitor_id'));
```

**2. Incorrect Root Domain**
Cookie set on wrong domain scope.

**Check:**

```javascript theme={null}
// Open browser DevTools → Application → Cookies
// Verify: __dl_visitor_id cookie domain is ".example.com" not "www.example.com"
```

**3. HTTPS/HTTP Mismatch**
Secure cookie not accessible on HTTP subdomain.

**Solution:**
Ensure all subdomains use HTTPS.

**4. SameSite Cookie Restrictions**
Browser blocking cross-site cookie access.

**Solution:**
DATALYR uses `SameSite=Lax` which allows same-site subdomain access.

### Visitor ID Not Passed Between Domains

**Symptoms:**

* New visitor ID generated on different domain
* Attribution lost

**Solutions:**

**1. Manual URL Parameter**
Add `_dl_vid` to links:

```javascript theme={null}
const visitorId = datalyr.getAnonymousId();
const url = `https://checkout.com?_dl_vid=${visitorId}`;
```

**2. Form Hidden Field**
Include visitor ID in form submissions:

```html theme={null}
<input type="hidden" name="_dl_vid" value="[visitor_id]">
```

**3. localStorage Fallback**
If cookies blocked, use localStorage + URL parameter:

```javascript theme={null}
// Source domain
const visitorId = datalyr.getAnonymousId();
localStorage.setItem('dl_cross_domain_vid', visitorId);

// Destination domain
const crossDomainVid = new URLSearchParams(window.location.search).get('_dl_vid');
if (crossDomainVid) {
  localStorage.setItem('dl_anonymous_id', crossDomainVid);
}
```

### Attribution Lost After Domain Change

**Symptoms:**

* Source/medium changes to "direct" after crossing domains
* UTM parameters lost

**Solutions:**

**1. Preserve UTM Parameters**
Include UTM parameters when linking between domains:

```javascript theme={null}
const currentParams = new URLSearchParams(window.location.search);
const utmParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content'];

const url = new URL('https://checkout.example.com');
utmParams.forEach(param => {
  if (currentParams.get(param)) {
    url.searchParams.set(param, currentParams.get(param));
  }
});

window.location.href = url.toString();
```

**2. Preserve Click IDs**
Include fbclid, gclid, etc.:

```javascript theme={null}
const clickIds = ['fbclid', 'gclid', 'ttclid', 'li_fat_id'];
clickIds.forEach(id => {
  if (currentParams.get(id)) {
    url.searchParams.set(id, currentParams.get(id));
  }
});
```

## Best Practices

**Install Tracking on All Domains/Subdomains**

```html theme={null}
<!-- Install on every domain and subdomain -->
<script defer src="https://track.datalyr.com/dl.js" data-workspace-id="ws_123"></script>
```

**Use Same Workspace ID**
All domains/subdomains must use the same `data-workspace-id`.

**Call identify() After Login**
Identify users immediately after login on any domain:

```javascript theme={null}
// After successful login on any domain
datalyr.identify(user.id, {
  email: user.email
});
```

**Preserve URL Parameters**
Don't strip UTM parameters or click IDs when redirecting between domains.

**Use HTTPS Everywhere**
Secure cookies require HTTPS. Use HTTPS on all domains/subdomains.

**Test Cookie Persistence**

```javascript theme={null}
// Check cookie on different subdomains
console.log('Visitor ID:', datalyr.getAnonymousId());
console.log('Cookie:', document.cookie.match(/__dl_visitor_id=([^;]+)/));
```

## Advanced Configuration

### Custom Domain for Checkout

**Scenario:** Checkout hosted on `checkout.yoursite.com` but different infrastructure.

**Solution:**

```javascript theme={null}
// Main site (www.yoursite.com)
<script defer src="https://track.datalyr.com/dl.js" data-workspace-id="ws_123"></script>

// Checkout site (checkout.yoursite.com)
<script defer src="https://track.datalyr.com/dl.js" data-workspace-id="ws_123"></script>

// Cookie automatically shared via .yoursite.com
```

### Multi-Brand Tracking

**Scenario:** Track users across multiple brand domains (brand1.com, brand2.com).

**Solution:**

```javascript theme={null}
// Pass visitor ID via URL between brands
const visitorId = datalyr.getAnonymousId();

// Redirect to other brand
window.location.href = `https://brand2.com?_dl_vid=${visitorId}`;

// Track as same visitor across brands
```

## Next Steps

<CardGroup cols={2}>
  <Card title="Visitor Identification" icon="fingerprint" href="/understanding-data/visitor-identification">
    How DATALYR identifies visitors
  </Card>

  <Card title="Identity Calls" icon="user" href="/understanding-data/identity-calls">
    Link users across sessions
  </Card>

  <Card title="Attribution Models" icon="chart-network" href="/understanding-data/attribution-models">
    How attribution works
  </Card>

  <Card title="Customer Journeys" icon="route" href="/features/customer-journeys">
    View complete user paths
  </Card>
</CardGroup>

## Need Help?

Questions about cross-domain tracking? Check our [troubleshooting guide](/troubleshooting/tracking-not-working) or contact support.
