What is Attributes?
Attributes hold the custom data
You can configure these attributes at different levels: users, accounts, catalog objects, and profile objects.
With this information, you can track, store, and utilize specific data, which can improve the personalization and effectiveness of your marketing strategies.
Code:
attributes: { [attributeName: string]: Attribute };
Example:
attributes: {
age: "25",
membershipStatus: "Gold Member",
lastPurchaseDate: "2024-05-15"
};
Code:
interface Attribute {
readonly value: AttributeValue;
readonly metadata?: Readonly<ValueMetadata>
}
Example:
attributes: {
age: {
value: 25, //string | number | boolean | Date | null | AttributeValueArray;
metadata: {
timestamp: new Date('2024-05-15'),
source: 'HR Database'
}
},
membershipStatus: {
value: "Gold Member" //string | number | boolean | Date | null | AttributeValueArray;
},
lastPurchaseDate: {
value: "2024-05-15" //string | number | boolean | Date | null | AttributeValueArray;
}
};
Code:
interface ValueMetadata {
origin?: string;
provider?: string;
gearId?: string;
lastUpdated?: Date;
lastVerified?: Date;
classification?: Classification;
}
type Classification = "Sensitive" | "PersonallyIdentifiable" | "NonSensitive";
Example:
attributes: {
age: {
value: 25, //string | number | boolean | Date | null | AttributeValueArray;
metadata: {
origin: "CRM",
provider: "CsvUserEtlJob:user-20230528.csv.gz",
gearId: "gear123",
lastUpdated: new Date('2024-05-15T10:00:00Z'),
lastVerified: new Date('2024-05-15T10:00:00Z'),
classification: "PersonallyIdentifiable"
}
},
membershipStatus: {
value: "Gold Member" //string | number | boolean | Date | null | AttributeValueArray;
metadata: {
origin: "LoyaltySystem",
provider: "LoyaltyService",
lastUpdated: new Date('2024-04-10T09:00:00Z'),
classification: "NonSensitive"
}
},
lastPurchaseDate: {
value: "2024-05-15" //string | number | boolean | Date | null | AttributeValueArray;
};
interface User {
attributes: { [key: string]: Attribute };
}
interface Attribute {
value: any; //string | number | boolean | Date | null | AttributeValueArray;
metadata?: {
origin?: string;
provider?: string;
gearId?: string;
lastUpdated?: Date;
lastVerified?: Date;
classification?: Classification;
};
}
Tips
How to fetch user attribute value?
Answer: user.attributes.someNum.value
An "interface" in programming is like a contract that says, "Any attribute must have these specific properties."
How to assign use attributes in SiteMap Code?
user: {
attributes: {
age: {
value: 25,
metadata: {
origin: "CRM",
provider: "CsvUserEtlJob:user-20230528.csv.gz",
gearId: "gear123",
lastUpdated: new Date('2024-05-15T10:00:00Z'),
lastVerified: new Date('2024-05-15T10:00:00Z'),
classification: "PersonallyIdentifiable"
}
}
}
}
Creating Attributes
function changeUserAttributes(user: User): void {
// Removing
delete user.attributes.nameToDelete;
delete user.attributes["bracketStyle"];
// Adding
user.attributes.someString = { value: "hi" };
user.attributes["someInt"] = {
value: 123,
metadata: { lastUpdated: new Date(), classification: "NonSensitive" },
};
user.attributes.someDecimal = { value: 123.45 };
user.attributes["someDate"] = { value: new Date(322376400000) };
user.attributes.someBool = { value: false };
user.attributes.someArray = { value: ["one", 2, null, new Date()] };
// Building up complex array to add
val = [];
val.push("Abigail");
val.push({ cell: "555-1234" });
val.push([2, 4, 6]);
val.push({ a: ["b"], c: { d: ["e", ["f"]] } });
val.push([{ one: 2, three: { four: [5, [6, 7]] } }, [8, { nine: 10 }]]);
meta = {};
meta.origin = "someOrigin";
meta.lastUpdated = new Date();
user.attributes.complexArray = { value: val, metadata: meta };
}
Reading Attributes
// Not fully safe examples:
function readingUserAttributeValuesUnsafely(user: User): void {
// Assuming attribute present and correct value type, simply casting:
let str: string = user.attributes.someString.value as string;
// Checking attribute present, then assuming correct value type and casting.
// Using undefined to represent not-present:
let num: number | undefined = !user.attributes.someNum
? undefined
: (user.attributes.someNum.value as number);
}
// Fully safe examples:
function readingUserAttributeValuesSafely(user: User): void {
// Handling all cases:
if (!user.attributes.someString) {
// Attribute not present
} else if (user.attributes.someString.value === null) {
// Attribute value null
} else if (typeof user.attributes.someString.value !== "string") {
// Attribute value not a string
} else {
const str: string = user.attributes.someString.value as string;
}
// Checking attribute present and value type.
// Using undefined to represent not-present or undesired-type:
let bool: boolean | undefined =
user.attributes.someBool && typeof user.attributes.someBool.value === "boolean"
? (user.attributes.someBool.value as boolean)
: undefined;
// Similar but as an if statement:
if (user.attributes.someBool && typeof user.attributes.someBool.value === "boolean") {
const bool: boolean = user.attributes.someBool.value as boolean;
}
// Similar but using guard functions:
if (user.attributes.someBool && isBoolean(user.attributes.someBool.value)) {
const bool: boolean = user.attributes.someBool.value;
}
if (user.attributes.someDate && isDate(user.attributes.someDate.value)) {
const date: Date = user.attributes.someDate.value;
}
if (user.attributes.complexArray && isArray(user.attributes.complexArray.value)) {
const arr: AttributeValueArray = user.attributes.complexArray.value;
if (arr.length > 0 && isNumber(arr[0])) {
const num: number = arr[0] as number;
}
}
}
// Guard functions:
// Currently the platform may provide a Date-like proxy, with getTime() etc. So avoid `instanceof`.
function isDate(value: AttributeValue): value is Date {
return typeof value === "object" && typeof (value as Date).getTime === "function";
}
function isArray(value: AttributeValue): value is AttributeValueArray {
return Array.isArray(value);
}
function isBoolean(value: AttributeValue): value is boolean {
return typeof value === "boolean";
}
function isString(value: AttributeValue): value is string {
return typeof value === "string";
}
function isNumber(value: AttributeValue): value is number {
return typeof value === "number";
}
function isNull(value: AttributeValue): value is null {
return value === null;
}