Core concepts for Fullstory's Element Properties API. Platform-agnostic guide covering API Defined Elements, property inheritance, schema types, and best practices...
Implementation Files: This document covers core concepts. For code examples, see:
- SKILL-WEB.md ā JavaScript/TypeScript (Browser)
- SKILL-IOS.md ā iOS (Swift/SwiftUI)
- SKILL-ANDROID.md ā Android (Kotlin/Java)
- SKILL-REACT-NATIVE.md ā React Native
- SKILL-FLUTTER.md ā Flutter (Dart)
Fullstory's Element Properties API allows developers to capture custom properties on UI elements that can be used for search, filtering, grouping, and analytics. Unlike standard attributes which are only used for CSS selectors, element properties become first-class data points for analysis, similar to user properties, page properties, and event properties.
Key capabilities:
data-fs-element attribute (web) or FS.setAttribute (mobile)| Type | Purpose | Searchable | Example |
|---|---|---|---|
| Attributes | CSS selectors, element matching | ā No | class="btn-primary" |
| Element Properties | Filtering, grouping, analytics | ā Yes | productId: "SKU-123" |
ā Good use cases:
ā Avoid for:
This is one of the most powerful features of Element Properties:
Two-way inheritance:
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
ā FORM (element="checkout-form") ā
ā ā
ā āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā ā
ā ā SHIPPING SELECT (selectedShipping="express") ā ā
ā āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā ā
ā ā
ā āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā ā
ā ā PAYMENT SELECT (selectedPayment="credit_card") ā ā
ā āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā ā
ā ā
ā āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā ā
ā ā GIFT WRAP CHECKBOX (giftWrap="true") ā ā
ā āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā ā
ā ā
ā āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā ā
ā ā SUBMIT BUTTON (element="submit-order") ā ā
ā ā āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā ā ā
ā ā When clicked, captures ALL properties from siblings: ā ā
ā ā ⢠selectedShipping: "express" ā ā
ā ā ⢠selectedPayment: "credit_card" ā ā
ā ā ⢠giftWrap: true ā ā
ā āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā ā
ā ā
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
Why this matters for analytics:
Key Insight: Define element properties on individual form fields, and the submit button will automatically capture the full form state. This eliminates the need to manually aggregate form data.
| Type | Description | Examples |
|---|---|---|
str |
String value | "foo", "bar", "foo@bar" |
strs |
Array of strings | ["foo", "bar"] |
int |
Integer | 0, -123, 45 |
ints |
Array of integers | [0, 1, 2] |
real |
Float/decimal | 12.345, -0.5 |
reals |
Array of reals | [12.345, 1] |
bool |
Boolean | true, false, 1, 0, t, f |
bools |
Array of booleans | [true, false] |
date |
ISO8601 date/datetime | "2006-01-02T15:04:05Z" |
dates |
Array of dates | ["2006-01-02", "2006-01-02T15:04:05Z"] |
| Type | Correct | Incorrect |
|---|---|---|
real |
199.99 |
"$199.99" (no currency symbols) |
int |
5 |
"5 items" (no units/text) |
bool |
true or "true" |
"yes", "Yes", "Y" |
date |
"2024-01-15T00:00:00Z" |
"today", "Jan 15" |
| Limit | Value |
|---|---|
| Active API Defined Elements | Max 1,000 (archived don't count) |
| Properties per single interaction | Max 50 unique |
| Properties across all interactions | Max 500 unique |
Container (e.g., product card)
āāā Properties: productId, productName, price, category
āāā Button (e.g., "Add to Cart")
āāā Inherits all container properties
āāā Button interaction captures full product context
Form Container
āāā Properties: formType, formStep, userTier
āāā Field 1
ā āāā Inherits form properties
ā āāā Own properties: fieldName, isRequired, fieldType
āāā Field 2
ā āāā Same pattern
āāā Submit Button
āāā Inherits form properties + captures all field properties
List Container
āāā Properties: listType, totalItems, filterApplied
āāā List Item (repeated)
āāā Inherits list properties
āāā Own properties: itemId, itemName, position
For all platforms, follow this order:
data-fs-element or equivalent)Setting the schema before values may cause timing issues with property capture.
| Do | Don't |
|---|---|
| Use clean numeric values | Include currency symbols ($, ā¬) |
| Use boolean true/false | Use "yes"/"no" strings |
| Use ISO8601 for dates | Use human-readable dates |
Use name override for readability |
Use raw attribute names |
| Focus on business-relevant data | Capture debug/technical data |
prepareForReuse() (iOS), onBindViewHolder (Android)| Symptom | Common Causes | Solutions |
|---|---|---|
| No properties captured | Schema set before values | Always set values before schema |
| No properties captured | Invalid JSON in schema | Use proper JSON builders, not manual strings |
| No properties captured | Attribute doesn't exist | Verify all schema attributes exist |
| No properties captured | Hit property limits | Check 50/500 limits |
| Symptom | Common Causes | Solutions |
|---|---|---|
| Stale data | View/cell reuse not handled | Implement prepareForReuse or clear in bind |
| Old attributes remain | Attributes not cleared | Track and clear previous attributes |
| Wrong timing | Attributes set at wrong lifecycle point | Set in appropriate lifecycle methods |
| Symptom | Common Causes | Solutions |
|---|---|---|
| Numbers show as strings | Values contain non-numeric chars | Strip formatting before setting |
| Booleans show as strings | Using "yes"/"no" | Use "true"/"false" strings |
| Dates not queryable | Wrong format | Use ISO8601 format |
name overridedata-fs-element (web) or equivalent (mobile)When helping developers implement Element Properties:
Always emphasize:
name overrideCommon mistakes to watch for:
Questions to ask developers:
Platform routing: