Use the Advanced builder to create segments

In this article...

We'll introduce you to our advanced segment builder, designed for those with experience of working with XML.

Intro

Unlike the Simple builder, which allows you to create segments without worrying about the underlying XML, the Advanced builder exposes the XML and gives you much greater flexibility and more options for segment customization.

On a technical level, each segment is an XML object, which you can view by opening the code view:

show code2

The XML object describes a segment's conditions in a way that can be read and understood by Qubit's Data Store, where we listen for QProtocol events triggered by visitor activity on your site and analyze them to determine segment membership.

Typically, you will define a segment in the Simple builder and then use the Advanced builder to edit the segment's XML object. Once live, Qubit's Segmentation Engine uses the XML definition to move visitors into and out of segments based on the real-time QProtocol events they are generating.

Editing the XML object

Step 1

▸ Create a new segment using the Simple builder and select Code view:

show code2

Step 2

▸ Select Edit code

Step 3

▸ Accept the disclaimer by selecting Let's Start

You can now use the Advanced builder interface to extend the segment's XML object.

WARNING: Once you switch to the Advanced builder, you cannot switch back to the Simple builder for the same segment.

Example XML object

The following example shows the XML object of a VIP Shoe Shoppers segment built using the Simple builder. This example segment targets visitors with a lifetime value of $500 or more that have purchased an item in the shoes category.

<segment>
  <and>
    <timeout type="view">
      <condition
        event="ecView"
        path="context.lifetimeValue.value"
        type="Money"
        op="gt"
        value="500"
      />
    </timeout>
    <timeout type="never">
      <condition
        event="ecBasketItemTransaction"
        path="product.categories"
        type="String"
        op="containsany"
        value="shoes"
      />
    </timeout>
  </and>
</segment>

Segment conditions, arguments, and attributes

Conditions are the fundamental building blocks of each segment. In turn, each condition consists of arguments and attributes.

Conditions

Incoming QProtocol events are evaluated against conditions. When all the conditions are met, the visitor generating those events be moved into or out of a segment.

In the example above, we will move the user into the segment if they purchase an item ecBasketItemTransaction from the product category shoes value="shoes" and has a lifetime value of 500 value=500.

INFO: The value you enter for the segment condition is case insensitive. Product category is shoes is the same as Product category is Shoes.

WARNING: To ensure a segment works as designed, you must wrap conditions in a stateful condition: <timeout>, <count>, <time>, query.

See Segment conditions for details of the available conditions.

Arguments

Arguments extend conditions. Refer to the following table:

Argument Name

Description

Supported Types/Operations

event

The QP event type to match

- This value is taken from the meta.type property of the event

- Event types might be prepended by a namespace, which is separated from the event type by a period .

- If a field key is not present, the key is a reference to the event itself, rather than any field within it. In this case, the left hand side of the expression will be an integer with the value 1.

path

The path to the field within the specified QP event

- The value of this field will be the left side of the expression. For simple events this would just be the field name, e.g. currency. However if you have a complex object, then the path references a specific node within the object graph, e.g. product.price. Note the use of . to descend into nested objects, for example context.sessionNumber will look at the field { context: { sessionNumber: 2 } }

type

The field type

- Necessary for comparison of the value in the condition and the value in the event

String,Number,Integer,Boolean,

Date,EpochTimeMS,UTCDate,UTCYear,

UTCMonth,UTCDayOfWeek,UTCDayOfMonth,

UTCHour,UTCMinute,LocalDate,

LocalYear,LocalMonth,LocalDayOfWeek,

LocalDayOfMonth,LocalHour,

LocalMinute

op

The expression operator

eq, neq, lt, lte, gt, gte, in,
nin, contains, ncontains,

containsany, ncontainsany, regex, nregex

- See Supported op argument operations for details of each supported operation

Attributes

Attributes further refine arguments. Refer to the following table:

Attribute Name

Supported Values

Description

type

never

Once any child condition is true, the timeout will remain true forever regardless of whether any child condition(s) returns to false

relative

Once any child condition is true, the timeout will remain true for the specified period
- If a child condition is true on a future evaluation, and after the relative duration expires, the timeout will be restarted for the period
- The unit attribute specifies the duration type (e.g. day, week, year), and the quantity attribute specifies the duration period

absolute

Becomes true if any child condition is true during the period, and will remain true until the end of the period
- The period is specified with the from and to attributes

session

Once any child condition is true, it remains true for the current session
- A session is a browsing period with no more than 30 minutes of inactivity and can contain multiple entrancesOnce triggered

entrance

Once any child condition is true, it remains true for the current entrance

view

Once any child condition is true, it remains true for the events in the current view

unit

millisecond

second

minute

hour

day

week

year

quantity

An integer value to specify how many of the given unit to remain true in a relative timeout

from

Timestamp specified either as an integer value specifying an epoch value in milliseconds, or a string containing a value which can be parsed by Date.parse()

inverted

true or false

If true, the result of the query (and all its children) is inverted.

Can be used to create a segment of people who are not in a dataset

Extending conditions with functions

Functions enable you to target visitors in a much more focused and creative way than can be achieved solely with conditions.

Combining conditions using and, nand, or

You can combine multiple conditions with a boolean function:

<and>
  // conditions
</and>
  • and - true if all the children are true
  • nand - true if any of the children are false
  • or - true if one or more of the children are true

Let's take a look at a few examples.

In this first example, we look to target visitors that were exposed to an experience variation.

CORRECT EXAMPLE

By wrapping both conditions around a single timeout, we ensure that each condition is evaluated at the same time and therefore only visitors exposed to the variation enter the segment:

<segment>
 <timeout type="never">
     <condition
       event="qubit.experience"
       path="experienceId"
       type="Integer"
       op="in"
       value="197604"
     />
     <condition
       event="qubit.experience"
       path="isControl"
       type="Boolean"
       op="eq"
       value="false"
     />
 </timeout>
</segment>

INCORRECT EXAMPLE

If we used separate timeouts for each condition, we would end up targeting visitors in the experience 197604 exposed to the variation in any Qubit experience.

This is because we will also perform the isControl test on events emitted by other experiences. So if the visitor is in the variation of any experience the condition will be met:

<segment>
 <timeout type="never">
     <condition
       event="qubit.experience"
       path="experienceId"
       type="Integer"
       op="in"
       value="197604"
     />
  </timeout>
  <timeout type="never">
     <condition
       event="qubit.experience"
       path="isControl"
       type="Boolean"
       op="eq"
       value="false"
     />
 </timeout>
</segment>

In this second example, we look to target visitors on mobile devices in a specific experience.

CORRECT EXAMPLE

By wrapping each condition with a timeout, we persist the state across events and ensure only visitors exposed to the experience on mobile devices enter the segment:

<segment>
  <and>
    <timeout type="session">
      <condition
        event="qubit.session"
        path="deviceType"
        type="String"
        op="in"
        value="mobile"
      />
    </timeout>
    <timeout type="never">
      <condition
        event="qubit.experience"
        path="experienceId"
        type="Integer"
        op="in"
        value="210135"
      />
    </timeout>
  </and>
</segment>

INCORRECT EXAMPLE

By wrapping the two conditions in a single timeout, that timeout will only become true if the two conditions are met at the same time. Since the events are emitted at different times, both conditions will never be true for this segment and so visitors would never join it:

<segment>
  <timeout type="never">
    <condition
      event="qubit.experience"
      path="experienceId"
      type="Integer"
      op="in"
      value="210135"
    />
    <condition
      event="qubit.session"
      path="deviceType"
      type="String"
      op="in"
      value="mobile"
    />
  </timeout>
</segment>

INFO: Without a stateful function like timeout or count, in a segment with multiple conditions that evaluate the same event type, we test all those conditions together against single events, even if multiple events of that type are emitted for a single view.

Using the count function to return the number of times all conditions are evaluated as true

The count function counts the number of times all conditions are true. This value is then applied to the operation specified in the function parameters. The result of this function is the result of the operation.

<count op="gte" value="2">

All arguments to the count function must be conditions, and they must all reference the same event.

Available operations:

  • eq - equal
  • neq - not equal
  • lt - less than
  • lte - less than or equal
  • gt - greater than
  • gte - greater than or equal

If a count is wrapped in a timeout, then the count will be timed out.

The following example shows a segment for visitors who have made a purchase more than once count op="gte value="2", of more than £10 op="gte" value="10, in the past 28 days timeout type="relative" duration="28 days":

<timeout type="relative" duration="28 days">
  <count op="gte" value="2">
    <condition
      event="ecBasketTransactionSummary"
      path="basket.total"
      op="gte"
      value="10"
    />
  </count>
</timeout>

Using the timeout function

Timeouts define how long a condition will remain true once evaluated as true. In the following example, once the visitor purchases shoes and triggers the condition and segment membership, the condition will remain true for 30 days. Upon expiry, the visitor will leave the segment:

<timeout
 type="relative"
 unit="day"
 quantity="30"
>
   <condition
     event="ecBasketItemTransaction"
     path="product.category"
     type="String"
     op="containsany"
     value="Shoes"
   />
 </timeout>

Available types and valid parameters are shown in the following table:

Type

Description

Parameters

never

condition's true state does not timeout

relative

conditions's true state will timeout after the period specified in the duration parameter has elapsed

duration - string, mandatory

The length of time the timeout should last for, e.g. 1 week, 3.5 days, 1 hour, 2 years

absolute

condition's true state will timeout after a period of time has elapsed, as specified in the from and to parameters

from - datetime, mandatory

The start date and time for the timeout period, format YYYY-MM-DD HH:MM

to - datetime, mandatory

The end date and time for the timeout period, format YYYY-MM-DD HH:MM

entrance

condition's true state will not timeout for the lifetime of N entrances

entrances - number, optional

The number of entrances in the past to consider, defaults to 1

session

condition's true state will not timeout for the lifetime of N sessions

sessions - number, optional

The number of sessions in the past to consider, defaults to 1

view

condition's true state will not timeout for the lifetime of N views

views - number, optional

The number of views in the past to consider, defaults to 1

event

condition's true state will not timeout for N instances of the event specified in the event and events parameters

event - string, mandatory

The event to consider

events - number, optional

The number of event occurrences in the past to consider, defaults to 1

In another example, we use the timeout function to target users who triggered an event, having never triggered it before. By using type="never" we ensure that the condition will not expire:

<segment>
<nand>
  <timeout
   type="never"
   >
    <condition
      event="ecInteraction"
      path="name"
      type="String"
      op="eq"
      value="hover-addToBag"
    />
  </timeout>
</nand>
</segment>

Inverted timeouts

Often, it is useful to target users who triggered an event in the past but haven't triggered that same event for a period of time. By adding inverted="true" to a timeout, the condition will be evaluated as true when the timeout expires rather than when it starts. This is useful for targeting lapsed customers:

<timeout type="relative" duration="10 days" inverted="true">
  <condition event="qubit.session" />
</timeout>

Using the time function

Whereas the timeout function is used to determine segment membership after an event has occurred, the time function allows you to fix segment membership for a period of time relative to the event datetime stamp.

You can use the following parameters:

Parameter

Description

event (mandatory string)

The event to target (same as condition)

path (mandatory string)

The path of the event to target (same as condition)

type (mandatory string)

The type of the value

op (mandatory string)

The operation in now {op} ({event}.{path} + {offset})

offset (optional string)

A time span that can be added to the event time so you can target before or after the specified time

value (mandatory string)

The current time to compare against

Examples of using the time function

On holiday

<and>
  <time
    event="trPackageItemTransaction"
    path="packageItem.journey.departureTs"
    type="EpochTimeMS"
    op="gt"
    value="now"
  />
  <time
    event="trPackageItemTransaction"
    path="packageItem.journey.arrivalTs"
    type="EpochTimeMS"
    op="lt"
    value="now"
  />
</and>

2nd trimester

<and>
  <time
    event="ecBabyDetails"
    path="birthdayTs"
    type="EpochTimeMS"
    op="gt"
    offset="-24.6 weeks"
    value="now"
  />
  <time
    event="ecBabyDetails"
    path="birthdayTs"
    type="EpochTimeMS"
    op="lt"
    offset="-12.3 weeks"
    value="now"
  />
</and>

Holiday ended yesterday

<time
  event="trPackageItemTransaction"
  path="packageItem.journey.arrivalTs"
  type="EpochTimeMS"
  op="gt"
  offset="1 day"
  value="now"
/>

Advanced segment examples

In this section, we will run through the steps of creating a segment for visitors that made more than two purchases and then look at some segment examples that can help you get started.

Example segment

Step 1 - Creating a simple segment

As always, we start by using the Simple builder to create our segment. We will then turn to the Advanced builder to develop our segment logic.

▸ Create your segment by selecting Segments from the side menu. Then select New Segment, enter a name for your segment, and select Let's start

▸ Select the Add condition combo box and select Total purchases

▸ Select Is more than and enter 2 in the field provided. In the Segment start date panel, select Custom and select a date from the calendar:

simple segment

By selecting a start date in the past, you can segment your visitors based on historical data generated on your site. For example, if you select a start date 30 days in the past, visitors can be segmented based on their activity during these 30 days. This is covered in detail in Including historical data


A quick note on custom variables and historical data

We do not lookup historical data for segments that check for custom variables, as shown in the following example:

<segment>
  <timeout type="never">
    <condition
      event="ecBasketItemTransaction"
      path="custom.product_division"
      type="String"
      op="containsany"
      value="men,girls,women"
      />
  </timeout>
</segment>

Step 2 - Extending the simple segment

We will now extend our simple segment to check for a second condition.

▸ Select Add condition and select Products purchased from Category

▸ Select Contains one of and enter Jeans into the field provided

Our updated segment will now include visitors that have made two purchases over their lifetime and has purchased an item in the product category Jeans:

simple segment

Step 3 - Editing segment code

By default, segment conditions are joined logically by AND—check for visitors that have made two purchases over their lifetime AND purchased in the product category Jeans.

However, we may want to modify this default behavior and use an OR in place of AND. To do this, we need to edit the segment's code.

▸ Select Code view, Edit code, and then Let’s start

▸ Now, replace the two instances of and with or:

<segment>
  <or>
    <timeout type="view">
      <condition
        event="ecView"
        path="context.conversionNumber"
        type="Integer"
        op="gt"
        value="2"
      />
    </timeout>
    <timeout type="never">
      <condition
        event="ecBasketItemTransaction"
        path="product.categories"
        type="String"
        op="containsany"
        value="Jeans"
      />
    </timeout>
  </or>
</segment>

Step 4 - Adding children

We will now finalize our segment's development by targeting visitors that made over two lifetime purchases and only ever bought jeans.

▸ Modify the remaining ecView event in the Example journey, changing conversionNumber to 2

▸ Once done, change the instances of <or> back to <and> in the segment code, and add the following lines underneath the last timeout:

<nand>
  <timeout type="never">
    <condition
      event="ecBasketItemTransaction"
      path="product.categories"
      type="String"
      op="nin"
      value="Jeans"
    />
  </timeout>
</nand>

The use of <nand> (negative-AND) returns false only if all its inputs are true. We use the operator nin to return true if the value in product.categories is not Jeans.

By combining <nand> with nin, only visitors that have made more than two purchases in their lifetime and purchased jeans will be present in the segment.

▸ To confirm the segment will do as we predict, add another ecBasketItemTransaction event, but this time add Socks to product.categories

In Example journey, you will see that this now removes the user from the segment:

ecBasketItemTransaction

▸ To complete the segment, select Save segment

Visitors who recently purchased shoes

In this example, we will create a segment for visitors that purchase shoes. We will remember the purchase for two weeks to fix segment membership for that period.

The relative timeout commences when the connected condition is evaluated as true. If the visitor purchases shoes again during those two weeks, the relative timeout will reset from this point, and we will extend segment membership for another two weeks.

<segment>
  <timeout type="relative" unit="week" quantity="2">
    <condition
      event="ecBasketItemTransaction"
      path="product.category"
      op="contains"
      value="Shoes"
    />
  </timeout>
</segment>

Visitors who bought one product but not another

By combining two conditions with a nand function, we can create a segment for visitors who have purchased a product from one category and have not purchased a product from another category.

We can use the ecBasketItemTransaction and path="product.category event to isolate the products purchased by a visitor in particular categories.

<segment>
  <and>
    <timeout type="never">
      <condition
        event="ecBasketItemTransaction"
        path="product.category"
        op="contains"
        value="Shoes"
      />
    </timeout>
    <nand>
      <timeout type="never">
        <condition
          event="ecBasketItemTransaction"
          path="product.category"
          op="contains"
          value="Socks"
        />
    </timeout>
    </nand>
  </and>
</segment>

Visitors who only ever bought one type of product

We can again use the product.category field of an ecBasketItemTransaction event to determine the products that have been previously purchased.

We can break this scenario down into two conditions:

  1. Has the visitor ever triggered an ecBasketItemTransaction event in a product category that contained shoes
  2. Has the visitor never triggered an ecBasketItemTransaction event in a product category that did not contain shoes
<segment>
  <and>
    <timeout type="never">
      <condition
        event="ecBasketItemTransaction"
        path="product.category"
        op="contains"
        value="Shoes"
      />
    </timeout>
    <nand>
      <timeout type="never">
        <condition
          event="ecBasketItemTransaction"
          path="product.category"
          op="ncontains"
          value="Shoes"
        />
      </timeout>
    </nand>
  </and>
</segment>

Visitors whose last purchase date was within the last 365 days

In this example, we will create a segment for visitors within an import called vistors_customer_profile whose last purchase date was within the last 365 days.

We will key off the user.id field in the ecUser event and take the purchase date from the import column LAST_PURCHASE_DATE.

We use the op argument with the operation lt in conjunction with offset to ensure that only those visitors that purchased in the last 365 days qualify for segment membership :

<segment>
  <timeout type="never">
    <query
      type="event"
      dataset="visitors_customer_profile"
      on="ecUser"
      key="user.id"
    >
      <column
        name="LAST_PURCHASE_DATE"
        type="EpochTimeMS"
        op="lt"
        offset="-365 days"
        value="now"
      />
    </query>
  </timeout>
</segment>

Visitors whose IP address matches a specific value

In this example, we will create a segment for visitors with an IP address that matches a specific value.

We use the in argument to return true when the visitors IP address matches. Equally though, you could use contains if you are looking to use an IP range:

<segment>
 <timeout type="session">
   <condition
     event="qubit.session"
     path="ipAddress"
     type="String"
     op="in"
     value="[your_IP_address]"
   />
 </timeout>
</segment>

Visitors other than logged-in VIP users

In this example, we will create a segment to target visitors that are not logged-in members of a dataset called vip_customer.

We do this by using the inverted attribute to invert the result of the query:

<segment>
 <query
   type="event"
   dataset="vip_customer"
   on="ecUser"
   key="user.id"
   inverted="true"
 />
</segment>

Validating your advanced segment

Especially for segments that contain a degree of complexity, we recommend validating the segment logic at regular intervals before final testing.

The best way to test a segment's logic is to simulate a user's journey on your site. Qubit gives you the flexibility to simulate this journey by giving you complete control over which events make up the visitor journey and in which order. You can also edit the events fields and values to simulate the journey according to the segment you are trying to create.

TIP: We recommend frequently validating as you make changes to a segment's code. Validating ensures that your users will be segmented correctly according to the segment's design and logic.

Using the segment we created in our example above, we will start by validating the first condition in our segment: Total purchases is more than 2.

▸ Select Add event to journey. Keep the default ecView event and click Add event.

At present, any user triggering this event would not enter the segment as context.conversionNumber is not present in the event, so validation fails:

ecView NOK

▸ To rectify this, add another ecView event to the example journey and add the following lines:

"conversionNumber": 3

The simulated journey is now successful in segmenting a fictitious user:

ecView OK

At this point, we need to check the second condition: Products purchased from category jeans

▸ To do this add the ecBasketItemTransaction event and replace the following line:

"categories": [],

With:

"product.categories": "Jeans",

▸ Now select Add event

Once again, the segment has passed the validation check. This is because of the OR that we used to join the two segment conditions. If we had retained the AND, the validation would have failed:

ecBasketItemTransaction OK

Testing

Before saving your segment to make it live, it is recommended that you test it to ensure that site activity triggers events that affect segment membership. You can do this using the Qubit Explorer.

FAQs

The answers to many more FAQs on segmentation can be found in Segmentation.

Are Segments cross-device?

Segment membership is currently not cross-device, except for segments that use external data imported into our Data Store.

For segments that use external data, if the imported join user identifier is device common, segments can target the visitor on any device where the identifier is seen based on a deterministic match. For instance, if a CRM gold customer's data set is imported keyed on user Ids, and these user Ids are common on mobile and desktop, the visitor will enter the segment on both devices.

Can external data be used when building segments?

Yes. It's possible to use Qubit Import to upload a dataset containing external segment memberships. You can then target these users by selecting the Imports condition.

When using the advanced builder, you can pass in the name of the dataset as shown above in the example Visitors whose last purchase date was within the last 365 days:

<query
 type="event"
 dataset="[name_of_dataset]"
 on="[event]"
 key="[event_field_to_key_off]"
>

See our tutorial Use imported data to create segments.

Where is segment membership stored? Can it be accessed server-side?

Each user's segment membership is stored in their cookie for performance reasons. Depending on your licensing agreement with Qubit, it is also possible to synchronize segment membership to our Data Store for server-side access.

I get an EntityRef: expecting ';' error when building my segment in advanced mode. How can I correct this?

Let's take a look at a simplified example where we will encounter this error:

<segment>
  <timeout type="view">
    <condition
      event="qubit.entrance"
      path="meta.url"
      type="String"
      op="containsany"
      value="gclid=,utm_medium,&utm"
    />
  </timeout>
</segment>

In XML, and other programming languages, such as HTML, & is used to insert a character reference. The correct reference for & (ampersand) is &amp;.

In our example, replacing &utm with &amp;utm will therefore correct the error:

<segment>
  <timeout type="view">
    <condition
      event="qubit.entrance"
      path="meta.url"
      type="String"
      op="containsany"
      value="gclid=,utm_medium,&amp;utm"
    />
  </timeout>
</segment>

Is whitespace trimmed from XML strings?

To answer this question, we'll look at another example:

<segment>
  <timeout type="never">
    <condition
      event="ecBasketItemTransaction"
      path="product.categories"
      type="String"
      op="containsany"
      value="Socks\, Red shoes\ ,shoes"
    />
  </timeout>
</segment>

In the above example, we will split on the comma and trim any whitespace before and after a comma.

Therefore the whitespace before and after Red shoes\ will be trimmed, but the whitespace in Red shoes will not.

Last updated: September 2021
Did you find this article useful?