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

# Integrating without IP tracking

> Set up SegmentStream without collecting user IP addresses by using hashed IPs and server-side geolocation.

If your organisation's privacy policy does not allow the collection or processing of user IP addresses, SegmentStream supports an alternative setup.

Instead of sending raw IP addresses, you can **hash** the IP (with salt) and **enrich it with geolocation data** on your side, before passing it to the SegmentStream data layer.

This approach ensures:

* No personally identifiable IP data is shared with SegmentStream.
* You still provide necessary contextual information (such as country, city, or region).
* Compliance with stricter data protection requirements (e.g. GDPR).

## 1. Required fields in the data layer

```javascript theme={null}
window.dataLayer = window.dataLayer || [];
window.dataLayer.push({
  event: 'user_context',
  ip_hash: '1e4b9f1a3d7e... (hashed and salted value)',
  country: 'DE',
  region: 'Berlin',
  city: 'Berlin',
});
```

### Field descriptions

| Field     | Type     | Description                                                                                            |
| --------- | -------- | ------------------------------------------------------------------------------------------------------ |
| `ip_hash` | `string` | Hashed (and salted) IP address. The hash ensures anonymity, and the salt prevents reverse-engineering. |
| `country` | `string` | Country code (e.g. `"DE"`, `"FR"`, `"US"`).                                                            |
| `region`  | `string` | Region or state.                                                                                       |
| `city`    | `string` | City name.                                                                                             |

## 2. How to prepare the IP address

All processing, including normalisation and hashing, should happen on your server. This ensures the raw IP address never leaves your infrastructure and that only anonymised data is shared with SegmentStream.

### Step 1: Normalise IPv6 addresses (server-side)

IPv6 addresses are more detailed than IPv4 and can include device-specific parts. To ensure privacy, the IPv6 address should be normalised to keep only the network portion (the first half) and replace the device-specific bits with zeros.

| Type       | IPv6 example                              | Meaning                                 |
| ---------- | ----------------------------------------- | --------------------------------------- |
| Full IPv6  | `2001:0db8:85a3:0000:0000:8a2e:0370:7334` | Device-level identifier                 |
| Normalised | `2001:0db8:85a3:0000:0000:0000:0000:0000` | Network-level identifier (safe to hash) |

```javascript theme={null}
// Run on your backend
function normalizeIPv6(ip) {
  if (!ip.includes(':')) return ip; // IPv4 - no normalization
  const segments = ip.split(':').slice(0, 4);
  while (segments.length < 8) segments.push('0000');
  return segments.join(':');
}
```

<Note>
  If the IP is IPv4, you can skip this step.
</Note>

### Step 2: Apply salted hashing (server-side)

After normalisation, hash the IP using a secure algorithm like SHA-256 and a private salt stored safely on your backend (e.g. in environment variables).

<Warning>
  * Do **not** hash or salt IPs in the browser.
  * The salt must remain secret and never be exposed to the client.
  * Only send the hashed IP and geo data to the frontend.
</Warning>

```javascript theme={null}
import crypto from 'crypto';

const SALT = process.env.IP_HASH_SALT; // store securely in environment variables

function hashIP(ip) {
  return crypto.createHash('sha256').update(ip + SALT).digest('hex');
}
```

Example output:

```text theme={null}
f2c992f0a9f8d5c8b87e1a2b36a52e5bce9df51de60cdb3eaf5d66a6dfdfe281
```

### Step 3: Example of each stage

| Step               | Description                         | Example                                      |
| ------------------ | ----------------------------------- | -------------------------------------------- |
| Full IPv6          | Original address                    | `2001:0db8:85a3:0000:0000:8a2e:0370:7334`    |
| Normalised         | Network-only portion (safe to hash) | `2001:0db8:85a3:0000:0000:0000:0000:0000`    |
| Hashed (with salt) | Final anonymised value              | `f2c992f0a9f8d5c8b87e1a2b36a52e5bce9df51...` |

## 3. Geolocation data

Use your own geolocation service (e.g. MaxMind, IP2Location, or a cloud provider's API) to extract country and region information before hashing.

## 4. Example architecture

Below is a complete setup showing where each process occurs.

### Server (Node.js / Python / etc.)

```javascript theme={null}
app.get('/api/user-context', async (req, res) => {
  const ip = getClientIP(req); // your logic for IP extraction
  const normalized = normalizeIPv6(ip);
  const hashed = hashIP(normalized);
  const geo = await lookupGeo(ip); // from your geolocation provider

  res.json({
    ip_hash: hashed,
    country: geo.country,
    region: geo.region,
    city: geo.city,
  });
});
```

### Client (browser)

```javascript theme={null}
(async () => {
  const context = await fetch('/api/user-context').then(r => r.json());

  window.dataLayer = window.dataLayer || [];
  window.dataLayer.push({
    event: 'user_context',
    ip_hash: context.ip_hash,
    country: context.country,
    region: context.region,
    city: context.city,
  });
})();
```

This way:

* The raw IP never leaves your infrastructure.
* The client receives only anonymised and geo-enriched data.
* SegmentStream operates in full privacy compliance.

## 5. Summary checklist

* [ ] Normalise IPv6 addresses on the server.
* [ ] Hash IPs with a private salt on the server.
* [ ] Send only hashed IP + geo data to the browser.
* [ ] Never expose the salt or raw IP in client code.
* [ ] Ensure consistency and privacy compliance.
