skills/analyst-user-profiling/SKILL.md
User identification, attribute management, and data collection governance.
npx skillsauth add delta-and-beta/braze-agency analyst-user-profilingInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
★ Insight ─────────────────────────────────────
This skill file uses imperative/infinitive form throughout ("Set the external_id..." not "You should set...") — a subtle but important convention because these files are consumed by AI, not humans, and direct instructions parse more reliably than advisory prose.
─────────────────────────────────────────────────
This skill governs how to identify users, enrich their profiles, and manage what data Braze collects — always balancing analytical completeness against data minimization principles. Apply it when designing user identity strategies, writing attribute-setting code, or advising on data governance tradeoffs.
This skill synthesizes three interconnected concerns:
| Topic | What It Covers |
|---|---|
| User IDs | Establishing persistent identity via external_id, managing anonymous users, alias-based identity |
| User Attributes | Setting standard and custom attributes, data types, update semantics |
| Data Collection Governance | Controlling what Braze collects, SDK data controls, compliance considerations |
The lens throughout is data governance: every recommendation weighs analytical value against collection minimization, consent scope, and downstream compliance risk.
external_id ContractBraze tracks users via an external_id — a stable, unique identifier owned by the implementation team (typically a database UUID or hashed email). Until an external_id is assigned, Braze generates an anonymous profile that:
To assign an external_id:
// Web SDK
braze.changeUser("usr_abc123");
// iOS SDK
Appboy.sharedInstance()?.changeUser("usr_abc123")
// Server-side (REST)
POST /users/track
{ "external_id": "usr_abc123", ... }
Governance considerations before assigning:
external_id — use opaque internal IDs, not emails or phone numbersexternal_id is permanent for that profile; reassignment creates orphaned dataAnonymous profiles accumulate session data, events, and purchases before login. On identification, Braze merges the anonymous profile into the identified one — but only forward from that point; historical anonymous events are not retroactively associated.
Design pattern: capture meaningful funnel events on anonymous profiles so the merged profile has pre-registration behavioral context.
User aliases provide a secondary identity layer — useful for:
braze.getUser().addAlias("salesforce_001", "salesforce_contact_id");
Aliases do not replace external_id; they supplement it. An alias pair is (alias_label, alias_name) — keep labels consistent across your integration or alias lookups will fail silently.
Braze provides built-in standard attributes (email, phone, first_name, language, country, etc.) with pre-built filtering support. Custom attributes extend the profile schema for domain-specific data.
Setting standard attributes:
const user = braze.getUser();
user.setEmail("[email protected]");
user.setFirstName("Ada");
user.setLanguage("en");
user.setCountry("US");
Setting custom attributes:
user.setCustomUserAttribute("subscription_tier", "pro");
user.setCustomUserAttribute("onboarding_completed", true);
user.setCustomUserAttribute("account_age_days", 42);
Custom attributes support these types:
| Type | Notes | |---|---| | String | Max 255 characters; truncated silently if exceeded | | Integer | Supports increment/decrement operations | | Float | Use for monetary values with care — floating point precision applies | | Boolean | Ideal for feature flags and consent tracking | | Date | ISO 8601; used for time-based segmentation | | Array | Max 25 elements; use for multi-value attributes like tag sets |
Increment semantics — for counters, prefer increment over set to avoid race conditions:
user.incrementCustomUserAttribute("login_count", 1);
Array operations — arrays support add/remove rather than full replacement:
user.addToCustomAttributeArray("interests", "photography");
user.removeFromCustomAttributeArray("interests", "gaming");
Before adding a new custom attribute, evaluate:
Avoid creating attributes "in case they're useful later." Unneeded attributes accumulate, inflate storage costs, and create compliance surface area.
Braze SDKs collect data automatically by default. Governance posture requires explicitly disabling collection that isn't needed.
Disable location tracking (if not used for geofencing/campaigns):
// Web SDK — disable automatic location collection
braze.initialize("API_KEY", {
enableGeolocation: false
});
Control session tracking:
// Manual session handling for kiosk/shared-device scenarios
braze.openSession();
braze.closeSession();
Wipe user data on logout (shared devices or strict consent models):
braze.wipeData(); // Deletes local SDK data; does not delete server-side profile
Note: wipeData() removes the local device_id and generates a new anonymous identity on next launch. Use deliberately — it breaks continuity for returning users on personal devices.
For GDPR/CCPA compliance workflows:
/users/delete REST endpoint, not SDK calls. SDK-side wipe only clears local state.email_subscribe / push_subscribe attribute to "unsubscribed" — do not delete the profile, as that loses suppression state.gdpr_consent_at, ccpa_opt_out_at) so consent history is queryable.Apply this filter before instrumenting any attribute or event:
Assign external_id only after explicit authentication, not on first app open. Capture funnel events on the anonymous profile until the user authenticates, then call changeUser() once.
Stale attributes mislead segmentation. Unset attributes when they no longer apply:
user.setCustomUserAttribute("trial_active", null); // Unsets the attribute
external_idUsing email as external_id creates problems when users change their email — the profile becomes orphaned. Use a stable internal UUID and store email as a standard attribute.
Tracking every conceivable user action inflates event volume costs and complicates data models. Define a tracking plan before instrumenting — instrument against campaign and analytics requirements, not as a "collect everything" strategy.
When advising on user data decisions, apply this sequence:
★ Insight ─────────────────────────────────────
The governance framework above follows a data minimization-first ordering — use case before collection, not collection before use case. This inverts the common anti-pattern of "collect everything, figure out usage later," which is both costly in Braze (event/attribute volume billing) and a compliance liability.
─────────────────────────────────────────────────
development
Cross-platform audience synchronization design across advertising platforms including Facebook, Google, TikTok, LinkedIn, and programmatic networks.
development
Defines cross-cutting API patterns for authentication, provisioning, preference management, and content delivery.
development
Covers API basics, authentication, rate limits, error codes, endpoint overview, data retention policies, and Postman collection usage.
development
Integration architecture for AI model providers including OpenAI, Google Gemini, and Anthropic within Braze messaging workflows.