Skip to content

Commit 440a110

Browse files
tpc-brianweissbc07claude
authored
UserId Submodule: add LocID (locId) (#6406)
* UserId Submodule: add LocID (locId) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Update LocID docs: atype 1, remove stable_cloc fallback, add connection_ip - Changed EID atype from 3384 to 1 (device-based identifier per OpenRTB 2.6) - Removed stable_cloc fallback language; module only uses tx_cloc for EID - Updated endpoint spec to return connection_ip for IP-aware cache invalidation - Clarified that stable_cloc is available for proxy operators, not transmitted client-side * Fix MD032 and MD058 markdownlint errors * LocID docs: add ipEndpoint param and IP change detection section * Docs: remove LocID legacy 3384/GVL references and clarify atype 1 --------- Co-authored-by: Brian <bcweiss@gmail.com> Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
1 parent 41b227d commit 440a110

1 file changed

Lines changed: 207 additions & 0 deletions

File tree

  • dev-docs/modules/userid-submodules
Lines changed: 207 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,207 @@
1+
---
2+
layout: userid
3+
title: LocID
4+
description: LocID User ID sub-module
5+
useridmodule: locIdSystem
6+
bidRequestUserId: locId
7+
eidsource: locid.com
8+
example: '"SYybozbTuRaZkgGqCD7L7EE0FncoNUcx-om4xTfhJt36TFIAES2tF1qPH"'
9+
---
10+
11+
## Overview
12+
13+
LocID is a geospatial identifier provided by Digital Envoy. The LocID User ID submodule retrieves a LocID from a publisher-controlled first-party endpoint, respects applicable privacy framework restrictions, and exposes the identifier to bidders via the standard EIDs interface.
14+
15+
The endpoint is a first-party or on-premises service operated by the publisher, GrowthCode, or Digital Envoy. The module does not transmit IP addresses from the browser; instead, the server-side endpoint derives location information.
16+
17+
## Registration
18+
19+
No registration is required to use this module. Publishers must configure a first-party endpoint that proxies requests to the LocID encryption service.
20+
21+
## Installation
22+
23+
Build Prebid.js with the LocID module:
24+
25+
```bash
26+
gulp build --modules=locIdSystem,userId
27+
```
28+
29+
## Configuration
30+
31+
### Default Mode
32+
33+
By default, the module proceeds when no privacy framework signals are present (LI-based operation):
34+
35+
```javascript
36+
pbjs.setConfig({
37+
userSync: {
38+
userIds: [{
39+
name: 'locId',
40+
params: {
41+
endpoint: 'https://id.example.com/locid',
42+
ipEndpoint: 'https://id.example.com/ip' // optional: lightweight IP-only check
43+
},
44+
storage: {
45+
type: 'html5',
46+
name: '_locid',
47+
expires: 7
48+
}
49+
}]
50+
}
51+
});
52+
```
53+
54+
### Strict Mode
55+
56+
To require privacy framework signals before proceeding, set `privacyMode: 'requireSignals'`:
57+
58+
```javascript
59+
pbjs.setConfig({
60+
userSync: {
61+
userIds: [{
62+
name: 'locId',
63+
params: {
64+
endpoint: 'https://id.example.com/locid',
65+
privacyMode: 'requireSignals'
66+
},
67+
storage: {
68+
type: 'html5',
69+
name: '_locid',
70+
expires: 7
71+
}
72+
}]
73+
}
74+
});
75+
```
76+
77+
### Configuration with API Key and Alternative ID
78+
79+
```javascript
80+
pbjs.setConfig({
81+
userSync: {
82+
userIds: [{
83+
name: 'locId',
84+
params: {
85+
endpoint: 'https://id.example.com/locid',
86+
apiKey: 'your-api-key',
87+
altId: 'publisher-user-id',
88+
timeoutMs: 1000,
89+
withCredentials: true
90+
},
91+
storage: {
92+
type: 'html5',
93+
name: '_locid',
94+
expires: 7
95+
}
96+
}]
97+
}
98+
});
99+
```
100+
101+
## Parameters
102+
103+
{: .table .table-bordered .table-striped }
104+
105+
| Param | Scope | Type | Description | Example |
106+
| --- | --- | --- | --- | --- |
107+
| name | Required | String | Module identifier. Must be `"locId"`. | `"locId"` |
108+
| params | Required | Object | Configuration parameters. | |
109+
| params.endpoint | Required | String | First-party LocID endpoint URL. See Endpoint Requirements below. | `"https://id.example.com/locid"` |
110+
| params.ipEndpoint | Optional | String | Separate lightweight endpoint returning only the connection IP. Used for IP change detection without a full tx_cloc fetch. | `"https://id.example.com/ip"` |
111+
| params.ipCacheTtlMs | Optional | Number | TTL for the IP cache entry in milliseconds. | `14400000` (4 hours, default) |
112+
| params.altId | Optional | String | Alternative identifier appended as `?alt_id=` query parameter. | `"user123"` |
113+
| params.timeoutMs | Optional | Number | Request timeout in milliseconds. | `800` (default) |
114+
| params.withCredentials | Optional | Boolean | Include credentials (cookies) on the request. | `false` (default) |
115+
| params.apiKey | Optional | String | API key passed via the `x-api-key` request header. | `"your-api-key"` |
116+
| params.privacyMode | Optional | String | Privacy mode: `"allowWithoutSignals"` (default) or `"requireSignals"`. | `"allowWithoutSignals"` |
117+
| params.requirePrivacySignals | Optional | Boolean | If `true`, requires privacy signals to be present. Equivalent to `privacyMode: 'requireSignals'`. | `false` (default) |
118+
| storage | Required | Object | Storage configuration for caching the ID. | |
119+
| storage.type | Required | String | Storage type. Use `"html5"` for localStorage. | `"html5"` |
120+
| storage.name | Required | String | Storage key name. | `"_locid"` |
121+
| storage.expires | Optional | Number | TTL in days. | `7` |
122+
123+
## Endpoint Requirements
124+
125+
The `endpoint` parameter must point to a first-party proxy or on-premises service, not the LocID Encrypt API directly.
126+
127+
The LocID Encrypt API requires the client IP address as a parameter. Since browsers cannot determine their own public IP, a server-side proxy is required to:
128+
129+
1. Receive the request from the browser
130+
2. Extract the client IP from the incoming connection
131+
3. Forward the request to the LocID Encrypt API with the IP injected
132+
4. Return the response (`tx_cloc`, `connection_ip`) to the browser
133+
134+
If `altId` is configured, the module appends it as `?alt_id=<value>` to the endpoint URL.
135+
136+
## Privacy Handling
137+
138+
LocID operates under Legitimate Interest (LI). The module's privacy behavior depends on the configured privacy mode.
139+
140+
### Default Behavior (allowWithoutSignals)
141+
142+
- **No privacy signals present**: Module proceeds and fetches the ID
143+
- **Privacy signals present**: Enforcement rules apply
144+
145+
### Strict Mode (requireSignals)
146+
147+
- **No privacy signals present**: Module returns `undefined`
148+
- **Privacy signals present**: Enforcement rules apply
149+
150+
### Privacy Signal Enforcement
151+
152+
When privacy signals are present, the module does not fetch or return an ID if any of the following apply:
153+
154+
- GDPR applies and vendorData is present, but consentString is missing or empty
155+
- US Privacy (CCPA) string indicates a processing restriction (third character is `Y`)
156+
- GPP signals indicate an applicable processing restriction
157+
158+
When GDPR applies and consentString is present, the module proceeds unless a framework processing restriction is signaled.
159+
160+
## Storage
161+
162+
The module caches the LocID using Prebid's standard storage framework. Configure storage settings via the `storage` object.
163+
164+
The endpoint response contains:
165+
166+
- `tx_cloc`: Transactional LocID (used as the EID value)
167+
- `connection_ip`: The resolved client IP address (used for IP-aware cache invalidation)
168+
169+
The module only uses `tx_cloc` for the EID. Any `stable_cloc` in the response is ignored client-side; it is available for proxy/endpoint operators to use in their own caching strategies.
170+
171+
### IP Change Detection
172+
173+
The module uses a two-tier cache to detect IP changes without churning the tx_cloc identifier:
174+
175+
- **IP cache** (default 4-hour TTL): Tracks the current connection IP in a separate localStorage key.
176+
- **tx_cloc cache** (configured via `storage.expires`): Stores the LocID via Prebid's userId framework.
177+
178+
When the IP cache expires, the module refreshes the IP. If `ipEndpoint` is configured, it makes a lightweight IP-only check first and only calls the main endpoint when the IP has changed. If the IP is unchanged and the tx_cloc cache is still valid, the existing tx_cloc is reused without calling the main endpoint.
179+
180+
## EID Output
181+
182+
When available, the LocID is included in the bid request as:
183+
184+
```json
185+
{
186+
"source": "locid.com",
187+
"uids": [{
188+
"id": "SYybozbTuRaZkgGqCD7L7EE0FncoNUcx-om4xTfhJt36TFIAES2tF1qPH",
189+
"atype": 1
190+
}]
191+
}
192+
```
193+
194+
The `atype` value of `1` is the OpenRTB agent type for web environment; it is not an IAB GVL vendor ID.
195+
196+
## Debugging
197+
198+
```javascript
199+
// Check if LocID is available
200+
pbjs.getUserIds().locId
201+
202+
// Force refresh
203+
pbjs.refreshUserIds()
204+
205+
// Check stored value
206+
localStorage.getItem('_locid')
207+
```

0 commit comments

Comments
 (0)