Skip to content

feat(audience): stamp consentLevel on Unity SDK messages#811

Closed
JCSanPedro wants to merge 2 commits into
mainfrom
SDK-565-unity-consent-level
Closed

feat(audience): stamp consentLevel on Unity SDK messages#811
JCSanPedro wants to merge 2 commits into
mainfrom
SDK-565-unity-consent-level

Conversation

@JCSanPedro

@JCSanPedro JCSanPedro commented Jul 2, 2026

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 |
+---------------------+----------+------------+---------+------------------------+-----------------+--------------------------------------+---------+---------------+------+

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 01:49
@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 force-pushed the SDK-565-unity-consent-level branch from fca1d08 to ac5f04f Compare July 2, 2026 02:28
@JCSanPedro JCSanPedro force-pushed the SDK-565-unity-consent-level branch from ac5f04f to 55348f6 Compare July 2, 2026 02:29
@JCSanPedro JCSanPedro changed the title feat(audience): stamp consentLevel on Unity SDK messages [SDK-565] feat(audience): stamp consentLevel on Unity SDK messages Jul 2, 2026
@JCSanPedro JCSanPedro closed this Jul 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant