Use the advanced builder
Use the advanced builder
This is for:
DeveloperIn 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:
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’ll 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’re generating.
Editing the XML object
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.
Once you switch to the Advanced builder, you can’t 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
.
Note
The value you enter for the segment condition is case insensitive.
Product category is |
To ensure a segment works as designed, you must wrap conditions in a stateful condition: |
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 |
|
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 (for example, currency). However if you have a complex object, then the path references a specific node within the object graph (for example, product.price). Note the use of |
|
type |
The field type- Necessary for comparison of the value in the condition and the value in the event |
|
op |
The expression operator |
|
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 (for example, |
|
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 |
|
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 <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/parse" target="blank">Date.parse()</a> |
|
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 aren’t 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>
Note
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.
The available operations include:
-
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, the count will be ended when the timeout period elapses.
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 doesn’t 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 (for example, 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 won’t 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 won’t 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 won’t 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 won’t 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 won’t 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’s 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 |
---|---|
|
The event to target (same as |
|
The path of the event to target (same as |
|
The type of the value |
|
The operation in |
|
A time span that can be added to the event time so you can target before or after the specified time |
|
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:
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 don’t 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:
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
isn’t 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’ll see that this now removes the user from the segment:
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 haven’t 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:
-
Has the visitor ever triggered an
ecBasketItemTransaction
event in a product category that contained shoes -
Has the visitor never triggered an
ecBasketItemTransaction
event in a product category that didn’t 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’re 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 aren’t logged-in members of a dataset called vipcustomer_.
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’re trying to create.
Leading practice
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:
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:
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:
Testing
Before saving your segment to make it live, we recommend 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 dataset 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’s 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 &
.
In our example, replacing &utm
with &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,&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
won’t.