Introduction
The Extraction Rules API provides programmatic access to create, read, update, and archive extraction rules. Extraction rules define how Fullstory captures structured data from your website or app — pulling values from page elements, URLs, and other sources into named properties for analytics.
Authentication
The HTTP API requires an API key that you can generate from the Fullstory app. The API key must have Admin or Architect level permissions for mutation operations. The header value takes the form "Basic {YOUR_API_KEY}".
Security Scheme Type: | apiKey |
|---|---|
Header parameter name: | Authorization |
Extraction Rules API Overview
Extraction rules pull structured data from page elements, URLs, or static values into named properties for analytics and segmentation. Each rule has a source (where to look), a scope (where to write the result), and one or more mappings (what to extract).
The API is archive-only. ArchiveExtractionRule stops a rule from capturing data but preserves it for audit history; UnarchiveExtractionRule restores it. There is no public delete RPC — permanent deletion is intentionally UI-only.
Concepts
Source — where the data comes from
A rule has exactly one source:
element(ElementSource) — matches page elements by selector. Each selector targets one or moreplatformvalues (PLATFORM_WEB,PLATFORM_IOS,PLATFORM_ANDROID) and carries a platform-specific selector string: a CSS selector for web, the view class name for iOS, or the fragment class name for Android. Multiple selectors in one rule combine with OR semantics.url(UrlSource) — matches the page URL. Setany: trueto consider every URL; per-mapping URL component selection happens inUrlValue(see below).
Scope — where the data goes
A rule has exactly one scope, applied to all of its mappings:
SCOPE_PAGE— writes to a page-scoped property (page name or a custom page property).SCOPE_USER— writes to a user-scoped property (uid, email, display name, or a custom user property).SCOPE_ELEMENT— writes to an element-scoped property.
Mapping — what to extract and where to write it
Each mapping has three parts:
- value source — exactly one of
element_value,url_value, orstatic_value.element_valuereads from the matched element. Useattributeto read an HTML attribute by name, or setinner_text: trueto read the element's text content.url_valuereads a piece of the URL. Set one of the boolean flagsfull,path,host, orfragmenttotrue, or set the string fieldqueryto the parameter name (for example"utm_campaign").static_valuewrites a fixed string regardless of page content.
- target — exactly one of the built-in Fullstory properties (
api_name,uid,email,display_name) or acustomPropertyidentified bynameanddata_type. - operation (optional) — a
ValueProducertransform applied to the raw value before it is written. Today the only supported transform is a regex (regex.expression, with an optionalregex.formatstring referencing capture groups like$1).
Active rule limits
Each org has a per-scope active_limit. Archiving a rule frees a slot; unarchiving consumes one. ListExtractionRules.usage_by_scope reports active_limit and active_count for each scope so callers can detect when an org is at the limit before attempting to create or unarchive.
Optimistic concurrency (etag)
Every rule has an opaque etag set by the server on read. Pass it on UpdateExtractionRule (PATCH) or Replace Extraction Rule (PUT). If the rule has changed since you read it, the server returns HTTP 409 Conflict — re-fetch, reconcile, and retry.
Updating rules: PATCH vs PUT
Two update endpoints sit on the same resource path:
PATCH /v2beta/extraction/rules/{id}(UpdateExtractionRule) — partial update. Send only the fields you want to change; the rest stay as they are.PUT /v2beta/extraction/rules/{id}(Replace Extraction Rule) — whole-resource replace. Send the complete rule body; every editable field is overwritten and unset fields are cleared.
Both honour the same etag flow. Choose PUT when you already hold the full intended rule state (for example, after editing it in your own UI). Choose PATCH when you only know the deltas.
PUT is friendly to a Get → mutate → PUT round-trip: server-managed fields on the rule body (created_at, updated_at, etag, archived) are silently ignored on input, so you can echo a Get response straight back without stripping fields. The body's id, if set, must agree with the id in the path.
Archive vs delete
This API is archive-only. ArchiveExtractionRule stops a rule from capturing data but preserves it for historical context. UnarchiveExtractionRule restores it (subject to active_limit). Permanent deletion is UI-only.
Unrepresented rules
Some legacy rules in an org cannot be modeled by the public API surface today. They count toward active_count but do not appear in List results. The unrepresented_count field on each scope of usage_by_scope reports how many such rules are present on the current page. Manage those rules from the Fullstory UI.
Worked Example: Capture product price from a cart element
This rule watches the cart summary on the web app, reads the data-price attribute off the matched element, strips the leading currency symbol with a regex, and writes the result into a custom page-scoped property product_price of type DATA_TYPE_FLOAT.
{
"rule": {
"name": "Capture Product Price",
"description": "Extracts the product price from the cart summary element",
"scope": "SCOPE_PAGE",
"source": {
"element": {
"selectors": [
{
"platform": ["PLATFORM_WEB"],
"selector": "#cart-summary .price"
}
]
}
},
"mappings": [
{
"element_value": {
"attribute": {
"attribute": "data-price"
}
},
"target": {
"custom": {
"name": "product_price",
"data_type": "DATA_TYPE_FLOAT"
}
},
"operation": {
"regex": {
"expression": "^(\\d+\\.\\d{2})"
}
}
}
]
}
}
Worked Example: Capture campaign from URL query parameter
This rule reads the utm_campaign query parameter from any page URL and writes it into a custom user-scoped property acquisition_campaign of type DATA_TYPE_STRING.
{
"rule": {
"name": "Capture utm_campaign",
"description": "Reads the utm_campaign query parameter into a user property",
"scope": "SCOPE_USER",
"source": {
"url": {
"any": true
}
},
"mappings": [
{
"url_value": {
"query": "utm_campaign"
},
"target": {
"custom": {
"name": "acquisition_campaign",
"data_type": "DATA_TYPE_STRING"
}
}
}
]
}
}