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
javascriptwindow.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.
Example:
Type | IPv6 Example | Meaning |
Full IPv6 | 2001:0db8:85a3:0000:0000:8a2e:0370:7334 | Device-level identifier |
Normalised (expanded) | 2001:0db8:85a3:0000:0000:0000:0000:0000 | Network-level identifier (safe to hash) |
Example normalisation function:
javascript// 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(':'); }
If the IP is IPv4, you can skip this step.
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).
The salt prevents reverse-engineering of hashed IPs.
- 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.
Example (Node.js):
javascriptimport 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:
javascriptuser_ip_hashed: 'f2c992f0a9f8d5c8b87e1a2b36a52e5bce9df51de60cdb3eaf5d66a6dfdfe281'
Step 3. Example of Each Stage
Step | Description | Example |
Full IPv6 | Original address | 2001:0db8:85a3:0000:0000:8a2e:0370:7334 |
Normalised (expanded) | Network-only portion (safe to hash) | 2001:0db8:85a3:0000:0000:0000:0000:0000 |
Hashed (with salt) | Final anonymised value | f2c992f0a9f8d5c8b87e1a2b36a52e5bce9df51de60cdb3eaf5d66a6dfdfe281 |
3. Geolocation Data
You should 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.)
javascriptapp.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(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.hashed_ip, country: context.geo_country, region: context.geo_region, city: context.geo_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.