Skip to content

Commit 952f615

Browse files
authored
Merge pull request #907 from IABTechLab/aul-UID2-5558-identity-map-v3-http-migration-guide
POST Identity Map V3 improvements and tests for sample code
2 parents ab61ebb + 3caf042 commit 952f615

8 files changed

Lines changed: 1195 additions & 6 deletions

File tree

docs/endpoints/post-identity-buckets.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ Used by: This endpoint is used mainly by advertisers and data providers. For det
1616
:::important
1717
If you're using the latest version of `POST /v3/identity/map`, v3, you don't need to use `POST /identity/buckets` at all. You only need to use it if you're using the earlier version, `POST /v2/identity/map`.
1818

19-
If you're using the earlier version, we recommend that you upgrade as soon as possible, to take advantage of improvements.
19+
If you're using the V2 version, we recommend that you upgrade as soon as possible, to take advantage of improvements. For migration guidance, see [Migration From V2 Identity Map](post-identity-map-v3.md#migration-from-v2-identity-map).
2020
:::
2121

2222
## Request Format

docs/endpoints/post-identity-map-v3.md

Lines changed: 89 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ The following are unencrypted JSON request body examples to the `POST /identity/
9595
}
9696
```
9797

98-
Here's an encrypted request example to the `POST /identity/map` endpoint for a phone number:
98+
Here's an encrypted request example to the `POST /identity/map` endpoint for phone numbers:
9999

100100
```sh
101101
echo '{"phone": ["+12345678901", "+441234567890"]}' | python3 uid2_request.py https://prod.uidapi.com/v3/identity/map [YOUR_CLIENT_API_KEY] [YOUR_CLIENT_SECRET]
@@ -115,7 +115,7 @@ The response arrays preserve the order of input arrays. Each element in the resp
115115

116116
Input values that cannot be mapped to a raw UID2 are mapped to an error object with the reason for unsuccessful mapping. An unsuccessful mapping occurs if the DII is invalid or has been opted out from the UID2 ecosystem. In these cases, the response status is `success` but no raw UID2 is returned.
117117

118-
The following example shows input and response.
118+
The following example shows the input and corresponding response.
119119

120120
Input:
121121

@@ -153,7 +153,7 @@ Response:
153153
"phone": [],
154154
"phone_hash": []
155155
},
156-
"status":"success"
156+
"status": "success"
157157
}
158158
```
159159

@@ -190,7 +190,92 @@ The following table lists the `status` property values and their HTTP status cod
190190
| Status | HTTP Status Code | Description |
191191
| :--- | :--- | :--- |
192192
| `success` | 200 | The request was successful. The response will be encrypted. |
193-
| `client_error` | 400 | The request had missing or invalid parameters.|
193+
| `client_error` | 400 | The request had missing or invalid parameters. |
194194
| `unauthorized` | 401 | The request did not include a bearer token, included an invalid bearer token, or included a bearer token unauthorized to perform the requested operation. |
195195

196196
If the `status` value is anything other than `success`, the `message` field provides additional information about the issue.
197+
198+
## Migration From V2 Identity Map
199+
200+
### Migration Overview
201+
202+
The V3 Identity Map API provides several improvements over V2:
203+
204+
- **Simplified Refresh Management**: Monitor for UID2s reaching `refresh_from` timestamps instead of polling <Link href="../ref-info/glossary-uid#gl-salt-bucket-id">salt buckets</Link> for rotation
205+
- **Previous UID2 Access**: Access to previous raw UID2s for 90 days after rotation for campaign measurement
206+
- **Single Endpoint**: Use only `/v3/identity/map` instead of both `/v2/identity/map` and `/v2/identity/buckets`
207+
- **Multiple Identity Types In One Request**: Process emails and phone numbers in a single request
208+
- **Improved Performance**: The V3 API uses significantly less bandwidth for the same amount of DII
209+
210+
### Key Differences Between V2 and V3
211+
212+
| Feature | V2 Implementation | V3 Implementation |
213+
|:-------------------------------|:--------------------------------------------|:-------------------------------------------|
214+
| **Endpoints Required** | `/v2/identity/map` + `/v2/identity/buckets` | `/v3/identity/map` only |
215+
| **Identity Types per Request** | Single identity type only | Multiple identity types |
216+
| **Refresh Management** | Monitor salt bucket rotations via `/identity/buckets` endpoint | Re-map when past `refresh_from` timestamps |
217+
| **Previous UID2 Access** | Not available | Available for 90 days |
218+
219+
### Required Changes
220+
221+
#### 1. **Update Endpoint URL**
222+
223+
```python
224+
# Before (V2)
225+
url = '/v2/identity/map'
226+
227+
# After (V3)
228+
url = '/v3/identity/map'
229+
```
230+
231+
#### 2. **Update V3 Response Parsing Logic**
232+
233+
**V2 Response Parsing**:
234+
```python
235+
# V2: Process mapped/unmapped objects with identifier lookup
236+
for item in response['body']['mapped']:
237+
raw_uid = item['advertising_id']
238+
bucket_id = item['bucket_id']
239+
original_identifier = item['identifier']
240+
# Store mapping using identifier as key
241+
store_mapping(original_identifier, raw_uid, bucket_id)
242+
```
243+
244+
**V3 Response Parsing**:
245+
```python
246+
# V3: Process array-indexed responses
247+
for index, item in enumerate(response['body']['email']):
248+
original_email = request_emails[index] # Use array index to correlate
249+
if 'u' in item:
250+
# Successfully mapped
251+
current_uid = item['u']
252+
previous_uid = item.get('p') # Available for 90 days after rotation, otherwise None
253+
refresh_from = item['r']
254+
store_mapping(original_email, current_uid, previous_uid, refresh_from)
255+
elif 'e' in item:
256+
# Handle unmapped with reason
257+
handle_unmapped(original_email, item['e'])
258+
```
259+
260+
#### 3. **Replace Salt Bucket Monitoring with Refresh Timestamp Logic**
261+
**V3 Approach (Refresh Timestamps)**:
262+
263+
```python
264+
import time
265+
266+
def is_refresh_needed(mapping):
267+
now = int(time.time() * 1000) # Convert to milliseconds
268+
return now >= mapping['refresh_from']
269+
270+
# Check individual mappings for refresh needs
271+
to_remap = [mapping for mapping in mappings if is_refresh_needed(mapping)]
272+
remap_identities(to_remap)
273+
```
274+
275+
### Additional Resources
276+
277+
For SDK-specific migration guidance, see:
278+
- [SDK for JavaScript V3](../sdks/sdk-ref-javascript-v3.md) for client-side implementations
279+
- [SDK for Java](../sdks/sdk-ref-java.md) for server-side implementations (see Usage for Advertisers/Data Providers section)
280+
281+
For general information about identity mapping, see [Advertiser/Data Provider Integration Overview](../guides/integration-advertiser-dataprovider-overview.md).

docs/endpoints/post-identity-map.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ For details about the UID2 opt-out workflow and how users can opt out, see [User
2020
This documentation is for version 2 of this endpoint, which is not the latest version. For the latest version, v3, see [POST /identity/map](post-identity-map-v3.md).
2121

2222
:::note
23-
If you're using the earlier version, we recommend that you upgrade as soon as possible, to take advantage of improvements.
23+
If you're using the V2 version, we recommend that you upgrade as soon as possible, to take advantage of improvements. For migration guidance, see [Migration From V2 Identity Map](post-identity-map-v3.md#migration-from-v2-identity-map).
2424
:::
2525

2626
## Batch Size and Request Parallelization Requirements

test/python/.gitignore

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
# Python
2+
__pycache__/
3+
*.py[cod]
4+
*$py.class
5+
*.so
6+
.Python
7+
build/
8+
develop-eggs/
9+
dist/
10+
downloads/
11+
eggs/
12+
.eggs/
13+
lib/
14+
lib64/
15+
parts/
16+
sdist/
17+
var/
18+
wheels/
19+
*.egg-info/
20+
.installed.cfg
21+
*.egg
22+
MANIFEST
23+
24+
# Virtual environments
25+
.env
26+
.venv/
27+
env/
28+
venv/
29+
ENV/
30+
env.bak/
31+
venv.bak/
32+
33+
# pytest
34+
.pytest_cache/
35+
.coverage
36+
htmlcov/
37+
.tox/
38+
.nox/
39+
.cache
40+
41+
# IDEs
42+
.vscode/
43+
.idea/
44+
*.swp
45+
*.swo
46+
*~
47+
48+
# macOS
49+
.DS_Store
50+
.AppleDouble
51+
.LSOverride
52+
53+
# Linux
54+
*~
55+
56+
# Windows
57+
Thumbs.db
58+
ehthumbs.db
59+
Desktop.ini
60+
$RECYCLE.BIN/
61+
62+
# Logs
63+
*.log
64+
65+
# Test results
66+
test-results/
67+
coverage.xml
68+
*.cover
69+
*.py,cover
70+
.hypothesis/
71+
72+
# Jupyter Notebook
73+
.ipynb_checkpoints
74+
75+
# pyenv
76+
.python-version
77+
78+
# pipenv
79+
Pipfile.lock
80+
81+
# poetry
82+
poetry.lock
83+
84+
# Celery
85+
celerybeat-schedule
86+
celerybeat.pid
87+
88+
# SageMath
89+
*.sage.py
90+
91+
# Environments
92+
.env
93+
.env.local
94+
.env.*.local
95+
96+
# mypy
97+
.mypy_cache/
98+
.dmypy.json
99+
dmypy.json
100+
101+
# Pyre type checker
102+
.pyre/
103+
104+
# Local test data
105+
test_data/
106+
temp/
107+
tmp/

test/python/README.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# UID2 Documentation Python Tests
2+
3+
This directory contains Python tests for the code samples in the [POST /identity/map v3 documentation](../../docs/endpoints/post-identity-map-v3.md). The tests verify that the Python code examples in the documentation work correctly and demonstrate proper usage patterns.
4+
5+
## Quick Start
6+
7+
### Prerequisites
8+
9+
1. **Install UV** (Python package manager):
10+
```bash
11+
pip install uv
12+
```
13+
14+
## Environment Configuration
15+
Fill the following environment variables into the `.env` file. The file is gitignored.
16+
- `UID2_BASE_URL` - Integration environment endpoint
17+
- `UID2_API_KEY` - Test API key
18+
- `UID2_SECRET_KEY` - Test secret key
19+
20+
### Run Tests
21+
```bash
22+
cd test/python
23+
uv run pytest
24+
```

test/python/pyproject.toml

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
[project]
2+
name = "uid2-docs-python-tests"
3+
version = "0.1.0"
4+
description = "Python tests for UID2 documentation code samples"
5+
requires-python = ">=3.8"
6+
dependencies = [
7+
"uid2-client>=3.0.0a1",
8+
"pytest>=7.0.0",
9+
"python-dotenv>=1.0.0",
10+
]
11+
12+
[project.optional-dependencies]
13+
dev = [
14+
"pytest-cov>=4.0.0",
15+
]
16+
17+
[tool.pytest.ini_options]
18+
testpaths = ["."]
19+
python_files = ["test_*.py"]
20+
python_classes = ["Test*"]
21+
python_functions = ["test_*"]
22+
addopts = [
23+
"-v",
24+
"--tb=short",
25+
"--disable-warnings",
26+
]
27+
filterwarnings = [
28+
"ignore::DeprecationWarning",
29+
"ignore::PendingDeprecationWarning",
30+
]

0 commit comments

Comments
 (0)