Skip to content

feat(audience): stamp consent level on Unity SDK messages#812

Merged
JCSanPedro merged 2 commits into
mainfrom
feat/unity-consent-level
Jul 2, 2026
Merged

feat(audience): stamp consent level on Unity SDK messages#812
JCSanPedro merged 2 commits into
mainfrom
feat/unity-consent-level

Conversation

@JCSanPedro

Copy link
Copy Markdown
Contributor

What

  • Stamps the current consent level onto every Unity SDK message in MessageBuilder.BuildBase() (threaded through Track/Identify/Alias), serialized as consentLevel (none/anonymous/full) to match the API.
  • On a Full → Anonymous downgrade, queued track messages now have consentLevel rewritten to anonymous alongside the existing userId strip — in both the in-memory EnqueueChecked transform and the on-disk DiskStore rewrite. The disk rewrite also normalises events persisted before consentLevel existed.

Why

Consent level is being plumbed end-to-end through the pipeline (SDK → audience ingest → attribution → postbacks) as part of SDK-449. Attribution currently infers consent from the presence of a userId, which cannot distinguish full-but-unidentified traffic from genuinely anonymous traffic. Sending the decided level explicitly lets the backend record provenance rather than guess.

This is the Unity half of SDK-565, mirroring the web/pixel SDK change (ts-immutable-sdk) and the audience-service ingest/derivation side (SDK-554, already landed and accepting the field as optional). Non-breaking, forward-compatible.

Notes:

  • Every build/enqueue path is consent-guarded (CanTrack/CanIdentify), so the stamped level is always a decided, sendable value (anonymous/full) — never none. Unity's ConsentLevel enum has no not_set (which the API rejects), so it can never be emitted.
  • The EnqueueChecked transform re-stamps under the drain lock so consentLevel reflects consent at enqueue time, closing the build→enqueue race the same way the existing userId strip does.

End-to-end validation (dev)

Ran the audience sample app against the dev environment and drove the consent flow (init full, identify, downgrade to anonymous). Confirmed in BigQuery (dev-im-cdp.cdp_raw.events) that every event emitted by this SDK carries consent_level, and can be identified as Unity traffic via surface = 'unity' (context.library = com.immutable.audience):

▶ bq query --project_id=dev-im-cdp --use_legacy_sql=false '
SELECT
  publish_time,
  JSON_VALUE(data, "$.type")                   AS type,
  JSON_VALUE(data, "$.eventName")              AS event_name,
  JSON_VALUE(data, "$.surface")                AS surface,
  JSON_VALUE(data, "$.context.library")        AS library,
  JSON_VALUE(data, "$.context.libraryVersion") AS library_version,
  JSON_VALUE(data, "$.anonymous_id")           AS anonymous_id,
  JSON_VALUE(data, "$.user_id")                AS user_id,
  JSON_VALUE(data, "$.consent_level")          AS consent_level,
  JSON_VALUE(data, "$.test")                   AS test
FROM `dev-im-cdp.cdp_raw.events`
WHERE JSON_VALUE(data, "$.anonymous_id") = "b2dca53a-9608-4e05-84b4-d35c13d8e76d"
ORDER BY publish_time DESC
LIMIT 100;'
Waiting on bqjob_r34ba1b3e1dd9c92_0000019f209c0245_1 ... (0s) Current status: DONE   
+---------------------+----------+------------+---------+------------------------+-----------------+--------------------------------------+---------+---------------+------+
|    publish_time     |   type   | event_name | surface |        library         | library_version |             anonymous_id             | user_id | consent_level | test |
+---------------------+----------+------------+---------+------------------------+-----------------+--------------------------------------+---------+---------------+------+
| 2026-07-02 02:13:44 | track    | NULL       | unity   | com.immutable.audience | 0.5.0           | b2dca53a-9608-4e05-84b4-d35c13d8e76d | NULL    | anonymous     | true |
| 2026-07-02 02:13:44 | track    | NULL       | unity   | com.immutable.audience | 0.5.0           | b2dca53a-9608-4e05-84b4-d35c13d8e76d | NULL    | anonymous     | true |
| 2026-07-02 02:13:43 | track    | NULL       | unity   | com.immutable.audience | 0.5.0           | b2dca53a-9608-4e05-84b4-d35c13d8e76d | NULL    | anonymous     | true |
| 2026-07-02 02:13:43 | track    | NULL       | unity   | com.immutable.audience | 0.5.0           | b2dca53a-9608-4e05-84b4-d35c13d8e76d | NULL    | anonymous     | true |
| 2026-07-02 02:13:08 | track    | NULL       | unity   | com.immutable.audience | 0.5.0           | b2dca53a-9608-4e05-84b4-d35c13d8e76d | john    | full          | true |
| 2026-07-02 02:13:08 | track    | NULL       | unity   | com.immutable.audience | 0.5.0           | b2dca53a-9608-4e05-84b4-d35c13d8e76d | john    | full          | true |
| 2026-07-02 02:12:08 | track    | NULL       | unity   | com.immutable.audience | 0.5.0           | b2dca53a-9608-4e05-84b4-d35c13d8e76d | john    | full          | true |
| 2026-07-02 02:12:07 | track    | NULL       | unity   | com.immutable.audience | 0.5.0           | b2dca53a-9608-4e05-84b4-d35c13d8e76d | john    | full          | true |
| 2026-07-02 02:12:07 | track    | NULL       | unity   | com.immutable.audience | 0.5.0           | b2dca53a-9608-4e05-84b4-d35c13d8e76d | john    | full          | true |
| 2026-07-02 02:12:07 | track    | NULL       | unity   | com.immutable.audience | 0.5.0           | b2dca53a-9608-4e05-84b4-d35c13d8e76d | john    | full          | true |
| 2026-07-02 02:12:07 | track    | NULL       | unity   | com.immutable.audience | 0.5.0           | b2dca53a-9608-4e05-84b4-d35c13d8e76d | john    | full          | true |
| 2026-07-02 02:11:52 | identify | NULL       | unity   | com.immutable.audience | 0.5.0           | b2dca53a-9608-4e05-84b4-d35c13d8e76d | john    | full          | true |
| 2026-07-02 02:11:27 | track    | NULL       | unity   | com.immutable.audience | 0.5.0           | b2dca53a-9608-4e05-84b4-d35c13d8e76d | NULL    | full          | true |
| 2026-07-02 02:11:27 | track    | NULL       | unity   | com.immutable.audience | 0.5.0           | b2dca53a-9608-4e05-84b4-d35c13d8e76d | NULL    | full          | true |
| 2026-07-02 02:11:27 | track    | NULL       | unity   | com.immutable.audience | 0.5.0           | b2dca53a-9608-4e05-84b4-d35c13d8e76d | NULL    | full          | true |
| 2026-07-02 02:11:17 | track    | NULL       | unity   | com.immutable.audience | 0.5.0           | b2dca53a-9608-4e05-84b4-d35c13d8e76d | NULL    | full          | true |
| 2026-07-02 02:11:12 | track    | NULL       | unity   | com.immutable.audience | 0.5.0           | b2dca53a-9608-4e05-84b4-d35c13d8e76d | NULL    | full          | true |
| 2026-07-02 02:11:12 | track    | NULL       | unity   | com.immutable.audience | 0.5.0           | b2dca53a-9608-4e05-84b4-d35c13d8e76d | NULL    | full          | true |
+---------------------+----------+------------+---------+------------------------+-----------------+--------------------------------------+---------+---------------+------+

JCSanPedro and others added 2 commits July 2, 2026 13:49
Stamp the current consent level onto every message in MessageBuilder.BuildBase
(threaded through Track/Identify/Alias), so the backend records the explicit
level rather than inferring it from userId presence. Every build/enqueue path
is consent-guarded, so only decided levels (anonymous/full) are ever stamped.

On a Full -> Anonymous downgrade, queued track messages now have consentLevel
rewritten to anonymous alongside the existing userId strip — in the in-memory
EnqueueChecked transform and the on-disk DiskStore rewrite (which also
normalises events persisted before consentLevel existed).

Mirrors the web/pixel SDK change (SDK-565) and the audience-service ingest
side (SDK-554).

Co-authored-by: Cursor <cursoragent@cursor.com>
@JCSanPedro JCSanPedro requested review from a team as code owners July 2, 2026 02:32
@JCSanPedro JCSanPedro changed the title feat(audience): stamp consent level in unity sdk messages feat(audience): stamp consent level on Unity SDK messages Jul 2, 2026
@github-actions

github-actions Bot commented Jul 2, 2026

Copy link
Copy Markdown

Audience SDK — Build Size

Platform SDK Size Change
Android 0.37 / 20.00 MB +0.00 MB
Windows 0.16 / 20.00 MB +0.00 MB
iOS 8.54 / 20.00 MB +0.02 MB
macOS 0.92 / 20.00 MB +0.02 MB

SDK Size = build minus empty app. Change = vs baseline. Fails if any platform exceeds its absolute size limit.

@JCSanPedro JCSanPedro merged commit 775fff6 into main Jul 2, 2026
115 of 134 checks passed
@JCSanPedro JCSanPedro deleted the feat/unity-consent-level branch July 2, 2026 22:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Development

Successfully merging this pull request may close these issues.

2 participants