User Attributes
User attributes are typed profile fields your organization defines in the Allegro admin — things like a newsletter opt-in, a favorite topic, or any preference you want a member to control. This guide covers reading and writing them from the browser with the SDK, which is how you'd build a preference center on your site.
Attributes are defined by an operator first. See the User Attributes product guide for how to create them and what the types mean.
These methods act on the currently authenticated member. Call them after the member has signed in — an unauthenticated visitor has no profile to read or write.
Reading a member's attributes
allegro.member.getUserAttributes() returns every defined attribute merged with
the current member's value, so you can render a whole preference form from one
call:
window.allegro.push(async function (allegro) {
const attributes = await allegro.member.getUserAttributes();
attributes.forEach(function (attribute) {
console.log(attribute.slug, attribute.value);
});
});
Each entry has the attribute's definition plus the member's current value:
| Field | Type | Description |
|---|---|---|
slug | string | The attribute key. |
name | string | The human-readable label. |
description | string | null | The optional description. |
type | string | string, number, boolean, enum, or color. |
options | string[] | null | The allowed choices, when the type is enum. |
value | unknown | The member's current value, or null when none is set. |
user_editable | boolean | Whether the member may set or clear this attribute themselves. |
private | boolean | Always false here. Private attributes are never returned by the session API. |
validation_rules | Array<{ type: string; value: string | number | null; message: string | null }> | null | The validation rules configured on the attribute, or null when none are set. Mirror these client-side to validate before submitting. |
Every defined attribute appears in the list, whether or not the member has set a value for it — except attributes the organization marked private, which are never returned.
Reading values at page load
getUserAttributes() makes a request. To read values as soon as the SDK has
loaded, without waiting on the network, use
allegro.member.userAttributesFromCache(). It returns the signed-in member's
values keyed by slug from a small localStorage cache, or null when the
member isn't signed in or nothing is cached yet:
window.allegro.push(function (allegro) {
const attributes = allegro.member.userAttributesFromCache();
if (attributes?.name_first) {
greeting.textContent = 'Welcome back, ' + attributes.name_first;
}
});
The SDK keeps the cache current on its own:
- It fills the cache when the member signs in, and on page load when the cache is missing or more than five minutes old. A stale value is still returned while the refresh runs.
- It clears the cache after every write from the SDK and fetches the new values in the background.
- It clears the cache on logout, and ignores a cache left by a different member.
Every fill or clear fires allegro:user-attributes:updated on window, with
{ values } in detail (null after a clear). In Alpine templates the same
values are on $store.allegro.userAttributes.
The cache is per origin, so www.example.org and plus.example.org each keep
their own copy. A change made somewhere else, such as in the admin or on another
device, shows up within five minutes.
Private attributes
An organization can mark an attribute private. The session API then behaves as if that attribute does not exist:
- It is left out of
getUserAttributes(). - Reading or writing it by slug fails with a
404USER_ATTRIBUTE_NOT_FOUNDerror — the same error you get for a slug that was never defined. - Its value is absent from the session token's
user_attributesclaim. - It cannot be placed on an
<allegro-form>.
There is no way to tell a private attribute from an undefined one through the session API, so nothing in the browser needs to handle the case specially. The organization's own systems still read and write the value through the token API, and it is still delivered on webhooks.
File attributes
Organizations can define file attributes that hold an uploaded file. Only
admins can set them, so the session API, the Browser SDK, and the token API
reject every write to one.
A private file attribute is hidden everywhere: the session API, the Browser SDK,
and the session token treat it as if it doesn't exist, and the token API doesn't
list it. A public file attribute reads like any other attribute, and its value
is the file's full public URL (or null when the member has no file):
window.allegro.push(async function (allegro) {
const attributes = await allegro.member.getUserAttributes();
const headshot = attributes.find(function (attribute) {
return attribute.slug === 'headshot';
});
// headshot.value: "https://cdn.example.com/user-attributes/.../1a2b3c4d-portrait.png"
});
The URL changes when an admin replaces the file.
Setting a value
allegro.member.setUserAttribute(slug, value) sets the value for the current
member and resolves with the stored value:
window.allegro.push(async function (allegro) {
await allegro.member.setUserAttribute('wants-newsletter', true);
});
The value must match the attribute's type — a boolean for a boolean attribute,
one of the defined options for an enum attribute, a hex string such as
#1a2b3c or #abc for a color attribute (stored and returned as lowercase
six-digit hex), and so on. <allegro-form> renders a color attribute with the
browser's native color picker. Text and number attributes can also carry
validation rules
an operator configures (length, pattern, numeric bounds, and so on). A value
that fails the type check or any of these rules is rejected with a 422
VALIDATION_ERROR, and the operator's configured (or default) message is
returned under data.errors.value:
{
"data": {
"code": "VALIDATION_ERROR",
"errors": { "value": ["Keep it under 5 characters."] }
}
}
Because that message is the one the operator wrote for the rule, you can surface
it directly to the member. Writing to a slug that isn't a defined attribute —
or is private — is rejected with a 404
USER_ATTRIBUTE_NOT_FOUND error.
If the attribute's user_editable flag is off, the request is rejected with a
403 USER_ATTRIBUTE_NOT_EDITABLE error — check the flag from
getUserAttributes() before showing the field as writable in a preference form.
Setting several values at once
allegro.member.setUserAttributes(values) takes the values keyed by attribute
slug and resolves with the stored values, so a preference form saves in one
round trip. A null value clears the member's stored value:
window.allegro.push(async function (allegro) {
const stored = await allegro.member.setUserAttributes({
'wants-newsletter': true,
'display-name': 'Jane',
color: null, // clears the stored value
});
});
The call is all-or-nothing: every slug is resolved and every value validated before anything is written, so nothing is saved if any single entry is bad. The three ways a call can fail each name the slugs responsible:
| Failure | Response |
|---|---|
| A slug isn't a defined attribute | 404 USER_ATTRIBUTE_NOT_FOUND, with the unknown slugs in data.slugs |
An attribute's user_editable flag is off | 403 USER_ATTRIBUTE_NOT_EDITABLE, with the blocked slugs in data.slugs |
| A value fails its type or validation rules | 422 VALIDATION_ERROR, with messages keyed values.<slug> |
Validation errors carry the operator's configured message for the rule, the same as the single-value endpoint, keyed by the attribute they belong to so a form can show each message against its own field:
{
"data": {
"code": "VALIDATION_ERROR",
"errors": {
"values.display-name": ["Keep it under 5 characters."],
"values.color": ["The selected color is invalid."]
}
}
}
Setting attributes when a member identifies
You can seed attribute values at the moment a member first identifies, before
they reach a preference form — for example to record where a signup came from.
Pass them to allegro.member.identifyByEmail(email, data?, attributes?), or set
the user-attributes attribute on an
<allegro-email-form>.
These values only fill attributes the member has no value for yet — an
existing value is never overwritten. The same validation and editability rules
as setUserAttributes apply: an unknown slug
fails with 404 USER_ATTRIBUTE_NOT_FOUND, a non-editable one with
403 USER_ATTRIBUTE_NOT_EDITABLE, and a bad value with 422 VALIDATION_ERROR
keyed by slug.
Clearing a value
allegro.member.deleteUserAttribute(slug) removes the member's value for an
attribute:
window.allegro.push(async function (allegro) {
await allegro.member.deleteUserAttribute('wants-newsletter');
});
Clearing is subject to the same user_editable check as setting a value, and
fails with the same 403 USER_ATTRIBUTE_NOT_EDITABLE error when the attribute
isn't editable by the member, or a 404 USER_ATTRIBUTE_NOT_FOUND error when it
is private.
Keeping the session token current
Setting or clearing values changes the member's session token —
attribute values are carried in its user_attributes claim. The SDK stores the
freshly-issued token automatically after each write, so a subsequent
allegro.member.getJwt() returns a token that reflects the change.
Related
- User Attributes product guide — Define attributes and their types in the admin.
- JWT Verification — Read attribute values from the session token.
MemberNamespace— Full SDK member API reference.