Skip to main content


Event dimensions

When data is loaded into Motif, it is represented as individual events, each made up of a dictionary of properties, or fields, which in Motif are called event dimensions. Motif needs to know 3 “core” dimensions to assemble events into sequences:

  • actor - identifier (who, usually user id), which is used to group events into sequences
  • ts - timestamp or number (when), which is used to order events within sequences
  • name - string field (what, usually event action), which is used as the initial event names.

events to sequences diagram

The 3 event dimensions, which are mapped to the “core” ones, get the additional actor, ts and name aliases, which can be used to reference them in Sequence Operation Language (SOL). All other event dimensions are also stored and are available for querying.

In SOL event dimensions are accessed through tags, which are labelled on top of events, for example:

match purchase
// Reference to the dimension "price" on the "purchase" event
set a = purchase.price

Tags can encompass multiple contiguous events. To reference dimensions on specific events, you can use Python-like list slicing:

match Cart(add_to_cart)+
// Array of "price" dimensions of all items added to cart
set a = Cart.price
// "Price" dimension of the item added to the cart first
set a = Cart[0].price
// "Price" dimension of the item added to the cart last
set a = Cart[-1].price
// "Price" dimensions of all items added to the cart, except for the first and last ones
set a = Cart[1:-1].price

SOL provides the set operation to modify and add event dimensions.

set gif

Here is a more complex example:

match Selecting()+ >> checkout
// Set "price" dimension on the "checkout" event to be the sum of prices of items added to the cart
set checkout.price = sum(if( = 'add_to_cart', Selecting.price, 0))

Here if() function performs an element-by-element array operation on a list of “name” dimensions for events in the Selecting tag. This is how SOL functions operate on arrays in general.

You can set event dimensions on all events by using the implicit SEQ tag, which references the whole sequence:

// Change event names to use other event dimensions
set = concat(, '_', SEQ.another_dim)

// Add 'gap' dimension by subtracting timestamp of the next event from the current one, using Python-like array slicing and element-by-element array operations
set SEQ[:-1].gap = SEQ[1:].ts - SEQ[:-1].ts

Sequence dimensions

SOL also supports defining and working with sequence dimensions - fields stored at the sequence level, rather than on individual events. They are referenced as independent variables and are not tied to tags. For example:

match search_page >> * >> watch_start
// Measure duration between "search_page" and "watch_start"
set search_to_watch_duration = watch_start.ts - search_page.ts
// Define long searches
set is_long_search = search_to_watch_duration > 15min

Note that there is currently no fool-proof way to avoid clashes between tag and sequence dimension names in SOL queries. SOL parser breaks this tie by first checking if there is a defined tag with the name in question and, if not, assumes that it is dealing with a sequence dimension. This is usually not an issue because Motif users create all tags in the same query.