After data is ingested into Hull, it is used for computation. The Compute stage is about calculating the difference or “diffs” between User or Account Reports and the existing indexed data. This is used to create User and Account Report Notifications to publish updates.
Updates are triggered when any of the following are ingested:
The associated User or Account objects are then marked as “dirty’ and recomputed.
Each User captured by Hull will have this event marking a moment when we first created that User in our database. No matter how the user get into out platform, this event will be emitted as first on the User timeline. The event properties will include all attributes captured at a time of creation plus created_at
.
In the context of this event you can find source
param which contains the connector, which allows you to easily track how the user was originally created. Obviously you can use it to filter users in following way:
And see all users who were created by the Incoming Webhooks connector:
You can view and manage Attributes in the Attributes view on the Dashboard.
Attributes can be marked as:
By default, attributes are marked as visible
. You need to go to the Attributes page on the User to change their status.
Note Only custom attributes can be marked as
visible + tracked
Status | Description |
---|---|
Hidden | Attributes will be hidden from the Dashboard and not be sent to external services |
Visible | Attributes will be ingested and visible in the dashboard, but no Attribute Changed events will be emitted. |
Visible + Tracked | Attributes will be ingested and visible in the dashboard, and Attribute Changed events will be emitted (e.g. use these Events to build Segments of previous Attributes values) |
Warning: Tracking
Attributes Changed
Events can create a lot of billable Incoming Requests. You can also create infinite loops with any dependent timestamped attributes. Best practice is to limit this only to Attributes where you use the change in values to run computations.
When one or more attribute marked as visible + tracked
are changed, Hull will generate an internal Event named Attributes changed
that contains the previous and new value of the attribute.
For instance, if one of your services is updating an attribute called mrr
on a user, and that value goes from 0
to 100
, an Attributes changed
event will be generated with the following properties:
{
"from/mrr": 0,
"to/mrr": 100
}
You will be able to use the Attributes Changed
event in the Segmentation engine to filter users.
If more than one attribute was changed by one connector, you might see multiple from/
and to/
properties in the same Event.
Different connectors will always generate different Attributes Changed
events even if they happen at the same time.
Note: This event will NOT be sent out to connectors. Connectors use the “Changes” object to detect updates to Attributes
Segments are used to group Entities who share common sets of properties and/or behaviors. You can create User Segments and Account Segments.
Segments are built via the Segmentation Tool in the Dashboard.
Segmentation is used to:
Segmentation queries are built from predicates. Predicates can be combined with “all” (AND) and “any” (OR) logic, visible in the query builder.
Hull supports three types of predicates:
Properties
(corresponding to Attributes)Events
Nested groups
(to create combinations of AND/OR logic)Hull supports the following predicates on properties:
These are transformed into queries as follows:
{
"type": "all",
"predicates": [{
"property": { "key": "first_name" },
"operator": "equals",
"options": { "value": [ "Romain" ] }
}]
}
Currently nested JSON object properties cannot be used for segmentation, but it may change in future. If you have specific needs in building a segment based on a nested JSON, contact us at support@hull.io to discuss your use case and how we can help.
Supported operators | Displayed as | Description |
---|---|---|
is_set is_not_set | Has any value, Is known | Tests the presence of a value for a given Attribute |
equals does_not_equal | Equals, Is not equal to | Strict equality of the whole string. Case sensitive. |
contains does_not_contain | Contains, Does not contain | Partial match within the string (tokens). Case & diacritics insensitive. |
starts_with does_not_start_with | Starts with, Does not start with | As with contains but testing only start of the whole value |
Note: contains
is not a full substring match. Some example searches:
value: "Hello Wørld"
=> contains "Hello" : true
=> contains "hello" : true
=> contains "world" : true
=> contains "ello" : false
=> contains "ello wo" : false
value: "hello@example.com"
=> contains "hello" : true
=> contains "hello@" : true
=> contains "hello@example" : true
=> contains "example" : true
=> contains "example.com" : true
=> contains "lo@ex" : false
Supported operators | Displayed as | Description |
---|---|---|
is_set is_not_set | Has any value, Is known | Tests the presence of a value for a given Attribute |
equals does_not_equal | Is equal to, Is not equal to | Tests for the equality of the value |
is_greater_than is_less_than | Is greater than, Is less than | Strict inequality comparison with a given number |
For example
value: 42
is_set: true
equals 42: true
is_greater_than 42: false
is_greater_than 41: true
Supported operators | Displayed as | Description |
---|---|---|
is_true | Is true | Value is set to true |
is_false | Is false | Value is set to false |
is_not_set | Is not set | No value is set for this Attribute |
Supported operators | Displayed as | Description |
---|---|---|
is_set is_not_set | Has any value, Is unknown | Has any value for this Attribute |
is_before is_after is_between | Absolute > Is before, Is after, Is between | Strict absolute inequality comparison with a given date based on UTC timezone. |
is_on is_not_on | Absolute > Is on, Is not on | Matches on a specific given date based on UTC timezone |
is_exactly is_less_than is_more_than is_betwee n_days | Relative > Is exactly, Is less than, Is more than, Is between | Relative date comparison in whole number of days. |
For example:
Today's date = 2018-05-04 (May 4th, 2018)
signup_date = 2018-04-01 (April 1st, 2018)
is_set: true
is_before 2018-05-01: true
is_on 2018-05-01: false
is_more_than 30: true
Hull enables you to query Events by:
Every Event query has an Occurrences and Timeframe filter. You can query Event Properties beneath each Event query with the “Where” button.
These are transformed into queries as follows:
{
"type": "all",
"predicates": [
{
"property": { "key": "event" },
"operator": "at_least_once",
"options": {
"eventName": "Completed Order",
"propsFilters": [{
"section": "property",
"key": "total",
"value": 100,
"operator": "gt"
}],
"timeframe": "less_than",
"days": 30
}
}
]
}
Supported operators | Displayed as | Description |
---|---|---|
zero_times | Zero times | No event recorded |
at_least_once | At least once (default) | Greater than 0 |
is_at_least | At least | Greater than value (strict inequality) |
is_at_most | At most | Less than value (strict inequality) |
equals | Exactly | Strictly equal to the value |
does_not_equal | Not exactly | Strictly not equal to the value |
Supported operators | Displayed as | Description |
---|---|---|
on , not_on , before , after | Absolute > on, not on, before, after | Comparison with a specified date |
between | Absolute > between | Comparison with 2 specified dates |
less_than , more_than , exactly | Relative > in the last, more than | Relative in number of days |
between_days | Relative > between | Relative between 2 values of “Days ago”. |
Any Event properties that have ever been associated with the selected Event will be displayed in a dropdown. This also includes the default Event Properties that Hull adds.
Supported operators | Displayed as | Description |
---|---|---|
contains | Contains | Partial match within the string of the Event Property (tokens). Case & diacritics insensitive. (Same as string search) |
Equals | Equals | Strict equality of the whole string within the Event Property. Case sensitive |
is_set is_not_set | Has any value, Is unknown | The Event Property either has or has not any value |
after before | After, Before | The Event Property is a date, either after or before the given date. |
gt lt | Greater than, Less than | The Event Property is numeric, either strictly greater than or less than |
is_true is_false | Is true, Is false | The Event Property is a boolean, either true or false |
You can combine combinations of AND and OR with Nested predicates. These are displayed as “Groups” within the Segmentation Tool query builder with all
and any
filters.
For example: (Country = United States OR Language = English) AND Job Title = “CEO”
These are transformed into queries as follows:
{
"type": "all",
"predicates": [{
"type": "any",
"predicates": [{
"property": { "key": "email" },
"operator": "is_set"
}, {
"property": { "key": "external_id" },
"operator": "starts_with",
"options": { "value": ["123"] }
}]
}]
}
Each time an Entity (Users and Accounts) are has new data, the list of Segments it belongs to is re-evaluated. New data includes:
Learn more about how data is ingested in Hull.
Segments with relative time predicates — “Users signed up less than 7 days ago” — are treated as live
Segments. Unless there is any other new data, all live Segments are recomputed on a rolling basis at least every 6 hours.
When a Segment is created, updated (and saved in Dashboard), or deleted, a Segment update
notification will be generated and emitted. - A few seconds after, new Memberships will be computed onto your Entities for this updated segment rules. - A notification will be sent to connectors so they can update Segment objects in third party tools (e.g. Facebook Custom Audiences, Mailchimp Lists).
Read more about Updates in Notify.
When an Entity enters or leaves a Segment, a Segments changed
event is captured in their timeline. Segments changed
events are one of three triggers for User and Account Updates.
For example:
{
"indexed_at": "2018-03-08T14:47:59+00:00",
"created_at": "2018-03-08T14:47:56Z",
"event": "Segments changed",
"source": "hull",
"type": "segment",
"props": [{
"field_name": "entered",
"text_value": [ "Never viewed dashboard or had demo" ]
}, {
"field_name": "left",
"text_value": [ "panda test", "Health Test" ]
}, {
"field_name": "entered_ids",
"text_value": [ "5aa13e004a6ef52f6000007d" ]
}, {
"field_name": "left_ids",
"text_value": [ "5a302c8fa79337b537002a17", "5a720d1d5cb250f6d5000070" ]
}],
"context": {
"days_since_signup": 457
}
}
This Event contains several interesting properties:
entered
: The names of the segments that the User entered.left
: The names of the segments that the User left.entered_ids
: The IDs of the segments that the User entered.left_ids
: The IDs of the segments that the User left.Days since Signup
: the number of days elapsed since we had an email stored from that User Profile.Note 1
This event is NOT emitted to connectors. You can use it for additional segmentation though. The
changes
object in the notifications can be used to leverage that information instead (See “changes”)