Filtering
What are Filters?
Filters are the decision-making engine of the Hood Web SDK. They determine whether an action (modal, push notification, tag execution) should run after a trigger fires. Think of filters as conditional logic that evaluates user data, browser information, and custom variables to make intelligent targeting decisions.
Filtering Pipeline
Event Occurs → Trigger Fires → Filters Evaluate → Action Executes (if filters pass)
Example: A user scrolls 50% down the page (trigger), the system checks if they’re from Germany OR using mobile (filters), and if any condition is true, shows a promotional modal (action).
Important Client-Side Limitation
Filters are executed exclusively client-side and are limited to data available to the SDK. This means:
- No server-side data: Filters cannot access server-side user profiles, purchase history, or other backend data
- Limited data scope: Only data explicitly set via
setuserproperties,identify,setVar, or available in browser context - Real-time only: Filters work with data available at the moment of evaluation, not historical data
- Privacy constraints: Cannot access sensitive server-side information for privacy and security reasons
Available data sources:
- User properties set via SDK methods (
data.*) - Browser information (
window.BW_INFO.*) - URL parameters (
url.*) - Cookies (
cookie.*) - Custom variables (
var.*) - Window/document properties (
window.*,document.*)
Not available:
- Server-side user profiles
- Complete purchase history
- Backend analytics data
- Historical user behavior
- Server-side personalization data
Filter Object Structure
Every filter is a JSON object with specific fields that define what to check, how to check it, and what value to compare against.
Filter Object Fields
c(string, required): Check expression - Variable to evaluate. If contains macros like{{data.country}}, they are resolved to their actual values before evaluationo(string, required): Operator - Comparison method (eq,gt,contains, etc.)m(string, required): Match value - Value to compare againstd(string, optional): Default - Value to use when check expression returns empty string or null. Prevents filter failures due to missing datacu(string, optional): Custom undefined - Value to use when check expression returnsundefined. Handles cases where variable doesn’t existcn(string, optional): Custom null - Value to use when check expression returnsnull. Provides fallback for null valuesct(string, optional): Custom true - Value to use when check expression returns booleantrue. Converts boolean to string for comparisoncf(string, optional): Custom false - Value to use when check expression returns booleanfalse. Converts boolean to string for comparisonf(string, optional): String formatting - Transforms the final value to lowercase (lc), uppercase (uc), or snake_case (sc) before any further processing. Does not affect the matching logic itself
Basic Example:
{
"c": "{{data.country}}",
"o": "eq",
"m": "DE"
}
Advanced Example:
{
"c": "{{data.user_segment}}",
"o": "eq",
"m": "premium",
"d": "free",
"cu": "unknown",
"f": "lc"
}
String Formatting Example:
// Without formatting - might fail due to case differences
{ "c": "{{data.user_type}}", "o": "eq", "m": "Premium" }
// With formatting - ensures consistent comparison
{ "c": "{{data.user_type}}", "o": "eq", "m": "premium", "f": "lc" }
// If data.user_type = "PREMIUM", it becomes "premium" before comparison
Field Definitions
Check Expression
Defines the variable or expression to evaluate. This is the “left side” of the comparison.
Usage:
{ "c": "{{data.country}}" }
{ "c": "{{window.BW_INFO.t}}" }
{ "c": "{{call.getCartTotal()}}" }
Macro Resolution: If the value contains macros like {{data.country}}, they are resolved to their actual values before evaluation. For example, {{data.country}} becomes "DE" if the user is from Germany.
Examples:
- Static value:
"premium" - User data:
"{{data.user_segment}}" - Browser info:
"{{window.BW_INFO.t}}" - Custom function:
"{{call.getCartTotal()}}"
Operator
Defines how the check value (c) is compared against the match value (m).
Available Operators:
- Equality:
eq,neq - Numeric:
gt,gte,lt,lte,between - String:
contains,startswith,endswith - Boolean/Existence:
isset,isempty,istrue,isfalse - Negated:
not.contains,isnset,isnempty, etc. - Advanced:
matchregex,matchcss
Usage:
{ "o": "eq" } // Equals
{ "o": "gt" } // Greater than
{ "o": "contains" } // Contains substring
Match Value
Defines the value to compare against the check expression result. This is the “right side” of the comparison.
Usage:
{ "m": "DE" } // String value
{ "m": "100" } // Numeric value
{ "m": "[50, 200]" } // Array for 'between' operator
Data Types: Can be string, number, boolean, or array depending on the operator used.
Important: Match values are static - they cannot contain macros like {{data.country}}. Only the check expression (c) supports macro resolution.
Default
Provides a fallback value when the check expression returns empty string or null.
When to use: Prevents filter failures due to missing or empty data.
Usage:
{
"c": "{{data.user_segment}}",
"o": "eq",
"m": "premium",
"d": "free" // Use "free" if user_segment is empty/null
}
Example: If {{data.user_segment}} returns "" or null, the filter will use "free" instead.
Custom Undefined
Provides a value when the check expression returns undefined.
When to use: Handles cases where the variable doesn’t exist or hasn’t been set.
Usage:
{
"c": "{{data.last_purchase}}",
"o": "isset",
"cu": "never" // Use "never" if last_purchase is undefined
}
Example: If {{data.last_purchase}} is undefined, the filter will use "never".
Custom Null
Provides a value when the check expression returns null.
When to use: Handles cases where the variable exists but has a null value.
Usage:
{
"c": "{{data.subscription}}",
"o": "eq",
"m": "active",
"cn": "inactive" // Use "inactive" if subscription is null
}
Example: If {{data.subscription}} is null, the filter will use "inactive".
Custom True
Provides a value when the check expression returns boolean true.
When to use: Converts boolean values to strings for comparison.
Usage:
{
"c": "{{data.newsletter_subscribed}}",
"o": "eq",
"m": "yes",
"ct": "yes" // Use "yes" if newsletter_subscribed is true
}
Example: If {{data.newsletter_subscribed}} is true, the filter will use "yes".
Custom False
Provides a value when the check expression returns boolean false.
When to use: Converts boolean values to strings for comparison.
Usage:
{
"c": "{{data.newsletter_subscribed}}",
"o": "eq",
"m": "no",
"cf": "no" // Use "no" if newsletter_subscribed is false
}
Example: If {{data.newsletter_subscribed}} is false, the filter will use "no".
String Formatting
Transforms the final value before any further processing.
Available Formats:
lc: Convert to lowercaseuc: Convert to uppercasesc: Convert to snake_case
Usage:
{
"c": "{{data.user_type}}",
"o": "eq",
"m": "premium",
"f": "lc" // Transform to lowercase
}
Example: If {{data.user_type}} returns "PREMIUM", it gets transformed to "premium" before comparison.
Note: This only transforms the value - it doesn’t affect the matching logic itself.
Operators Reference
Operators define how the check value (c) is compared against the match value (m). The SDK supports multiple categories of operators for different data types and comparison needs.
Equality Operators
eq - Equals (exact match)
- Description: Exact match using loose equality
- Example:
"DE" eq "DE"→ ✅ True - Usage:
{ "c": "{{data.country}}", "o": "eq", "m": "DE" }
neq - Not equals
- Description: Values are not equal
- Example:
"US" neq "DE"→ ✅ True - Usage:
{ "c": "{{data.plan}}", "o": "neq", "m": "free" }
Numeric Operators
gt - Greater than
- Description: Value is greater than match value
- Example:
100 gt 50→ ✅ True - Usage:
{ "c": "{{data.age}}", "o": "gt", "m": "18" }
gte - Greater than or equal
- Description: Value is greater than or equal to match value
- Example:
50 gte 50→ ✅ True - Usage:
{ "c": "{{data.age}}", "o": "gte", "m": "18" }
lt - Less than
- Description: Value is less than match value
- Example:
25 lt 50→ ✅ True - Usage:
{ "c": "{{data.score}}", "o": "lt", "m": "100" }
lte - Less than or equal
- Description: Value is less than or equal to match value
- Example:
50 lte 50→ ✅ True - Usage:
{ "c": "{{data.score}}", "o": "lte", "m": "100" }
between - Between range
- Description: Value is between min and max (expects array
[min, max]) - Example:
75 between [50, 100]→ ✅ True - Usage:
{ "c": "{{data.age}}", "o": "between", "m": "[25, 65]" }
Common usage:
{ "c": "{{data.age}}", "o": "gte", "m": "18" }
{ "c": "{{call.getCartTotal()}}", "o": "between", "m": "[50, 200]" }
Note: Numeric operators automatically convert values to numbers. Non-numeric values return false.
String Operators
contains - Contains substring
- Description: Checks if string contains substring (case-insensitive)
- Example:
"Hello World" contains "world"→ ✅ True - Usage:
{ "c": "{{data.email}}", "o": "contains", "m": "@gmail.com" } - Array Support: Also works with arrays - checks if array includes the match value
startswith - Starts with
- Description: Checks if string starts with prefix (case-insensitive)
- Example:
"JavaScript" startswith "java"→ ✅ True - Usage:
{ "c": "{{url.path}}", "o": "startswith", "m": "/checkout" }
endswith - Ends with
- Description: Checks if string ends with suffix (case-insensitive)
- Example:
"document.pdf" endswith ".pdf"→ ✅ True - Usage:
{ "c": "{{data.filename}}", "o": "endswith", "m": ".pdf" }
Boolean & Existence Operators
isset - Is defined
- Description: Checks if value is not
undefinedornull - Example:
"value" isset→ ✅ True - Usage:
{ "c": "{{data.email}}", "o": "isset", "m": "" }
isempty - Is empty
- Description: Checks if value is empty string, array, or object
- Example:
"" isempty→ ✅ True - Usage:
{ "c": "{{data.cart}}", "o": "isempty", "m": "" }
istrue - Is true
- Description: Checks if value is boolean
trueor string"true" - Example:
true istrue→ ✅ True - Usage:
{ "c": "{{data.premium}}", "o": "istrue", "m": "" }
isfalse - Is false
- Description: Checks if value is boolean
falseor string"false" - Example:
false isfalse→ ✅ True - Usage:
{ "c": "{{data.subscribed}}", "o": "isfalse", "m": "" }
Usage:
{ "c": "{{data.user_id}}", "o": "isset" }
{ "c": "{{data.newsletter}}", "o": "istrue" }
{ "c": "{{data.cart_items}}", "o": "isempty" }
Empty Check Details:
- Strings:
trim() === "" - Arrays:
length === 0 - Objects:
Object.keys().length === 0 null: considered emptyundefined: not considered empty
Negated Operators
All string and boolean operators have negated versions:
not.contains - Does not contain
- Description: Checks if string does NOT contain substring
- Example:
"Hello" not.contains "World"→ ✅ True - Usage:
{ "c": "{{data.email}}", "o": "not.contains", "m": "@competitor.com" }
not.startswith - Does not start with
- Description: Checks if string does NOT start with prefix
- Example:
"file.txt" not.startswith "doc"→ ✅ True - Usage:
{ "c": "{{url.path}}", "o": "not.startswith", "m": "/admin" }
not.endswith - Does not end with
- Description: Checks if string does NOT end with suffix
- Example:
"image.jpg" not.endswith ".png"→ ✅ True - Usage:
{ "c": "{{data.filename}}", "o": "not.endswith", "m": ".tmp" }
isnset - Is not set
- Description: Checks if value is
undefinedornull - Example:
undefined isnset→ ✅ True - Usage:
{ "c": "{{data.optional}}", "o": "isnset", "m": "" }
isnempty - Is not empty
- Description: Checks if value is NOT empty
- Example:
"Hello" isnempty→ ✅ True - Usage:
{ "c": "{{data.cart}}", "o": "isnempty", "m": "" }
isntrue - Is not true
- Description: Checks if value is NOT boolean
true - Example:
false isntrue→ ✅ True - Usage:
{ "c": "{{data.verified}}", "o": "isntrue", "m": "" }
isnfalse - Is not false
- Description: Checks if value is NOT boolean
false - Example:
true isnfalse→ ✅ True - Usage:
{ "c": "{{data.active}}", "o": "isnfalse", "m": "" }
### Advanced Operators
**`matchregex` - Regex match (case-sensitive)**
- Description: Tests value against regular expression pattern
- Example: `"[email protected]" matchregex "^[^@]+@[^@]+\\.[^@]+$"` → ✅ True
- Usage: `{ "c": "{{data.email}}", "o": "matchregex", "m": "^[^@]+@[^@]+\\.[^@]+$" }`
**`matchregexi` - Regex match (case-insensitive)**
- Description: Tests value against regular expression pattern (case-insensitive)
- Example: `"[email protected]" matchregexi "^[^@]+@[^@]+\\.[^@]+$"` → ✅ True
- Usage: `{ "c": "{{data.email}}", "o": "matchregexi", "m": "^[^@]+@[^@]+\\.[^@]+$" }`
**`notmatchregex` - Regex no match (case-sensitive)**
- Description: Tests that value does NOT match regex pattern
- Example: `"invalid" notmatchregex "^[^@]+@[^@]+\\.[^@]+$"` → ✅ True
- Usage: `{ "c": "{{data.input}}", "o": "notmatchregex", "m": "^[0-9]+$" }`
**`notmatchregexi` - Regex no match (case-insensitive)**
- Description: Tests that value does NOT match regex pattern (case-insensitive)
- Example: `"invalid" notmatchregexi "^[^@]+@[^@]+\\.[^@]+$"` → ✅ True
- Usage: `{ "c": "{{data.input}}", "o": "notmatchregexi", "m": "^[0-9]+$" }`
**`matchcss` - CSS selector match**
- Description: Tests if value matches CSS selector pattern
- Example: `"btn-primary" matchcss ".btn-primary"` → ✅ True
- Usage: `{ "c": "{{data.user_class}}", "o": "matchcss", "m": ".premium-user" }`
**`not.matchcss` - CSS selector no match**
- Description: Tests if value does NOT match CSS selector pattern
- Example: `"btn-secondary" not.matchcss ".btn-primary"` → ✅ True
- Usage: `{ "c": "{{data.element_class}}", "o": "not.matchcss", "m": ".disabled" }`
**Safety**: Regex patterns are validated to prevent catastrophic backtracking attacks.
## Macros and Data Sources
Macros allow you to access dynamic data from various sources using the `{{namespace.property}}` syntax. They're **resolved at runtime** - when a filter evaluates, macros like `{{data.country}}` are replaced with their actual values (e.g., `"DE"`) before the comparison happens. This enables dynamic filtering based on real-time data.
Info
Client-Side Data Only
Remember: All macro data sources are client-side only. The SDK can only access data that has been explicitly made available in the browser context through SDK methods or browser APIs. Server-side data, complete user profiles, or backend analytics are not accessible to filters.
### Data Namespaces
**Available Data Sources**
| Namespace | Description | Example | Use Case |
|-----------|-------------|---------|----------|
| `data.*` | **User properties** set via `setuserproperties` or `identify` | `{{data.country}}` | User segmentation |
| `var.*` | **Transient variables** set via `setVar` | `{{var.cart_total}}` | Session data |
| `cookie.*` | **Browser cookies** | `{{cookie.session_id}}` | Session tracking |
| `window.*` | **Window object properties** | `{{window.BW_INFO.t}}` | Browser detection |
| `document.*` | **Document properties** | `{{document.title}}` | Page context |
| `url.*` | **Current URL parts** | `{{url.host}}` | Page targeting |
| `referrer.*` | **Referrer URL parts** | `{{referrer.host}}` | Traffic source |
| `session.*` | **Session data** | `{{session.vt}}` | Visit tracking |
| `utm.*` | **UTM parameters** | `{{utm.campaign}}` | Campaign tracking |
| `partner.*` | **Partner/ad platform data** | `{{partner.fbclid}}` | Retargeting |
**Examples**:
```json
{ "c": "{{data.user_segment}}", "o": "eq", "m": "premium" }
{ "c": "{{window.BW_INFO.t}}", "o": "eq", "m": "mobile" }
{ "c": "{{url.path}}", "o": "contains", "m": "/checkout" }
Macro Resolution Example:
// Filter definition
{ "c": "{{data.country}}", "o": "eq", "m": "DE" }
// At runtime, if data.country = "DE", the filter becomes:
{ "c": "DE", "o": "eq", "m": "DE" }
// Result: ✅ True
Browser Information (BW_INFO)
Browser Detection Data
The SDK automatically collects browser information in window.BW_INFO:
| Property | Description | Example Values |
|---|---|---|
n | Browser name | "chrome", "firefox", "safari" |
v | Browser version | "120", "119" |
t | Device type | "mobile", "desktop" |
https | HTTPS support | 1 (yes), 0 (no) |
z | Timezone offset | "-300" (EST), "0" (UTC) |
ls | LocalStorage available | 1 (yes), 0 (no) |
wv | WebView detection | 1 (yes), 0 (no) |
ul | User language | "en", "de", "fr" |
pe | Push notifications enabled | 1 (yes), 0 (no) |
Usage:
{ "c": "{{window.BW_INFO.t}}", "o": "eq", "m": "mobile" }
{ "c": "{{window.BW_INFO.ul}}", "o": "eq", "m": "en" }
{ "c": "{{window.BW_INFO.pe}}", "o": "eq", "m": "1" }
Custom Functions
Function Calls
You can call any JavaScript function that exists in the window object using the call.* namespace:
Syntax: {{call.functionName(arg1, arg2)}}
How it works: The SDK looks for functions in two places:
- Registered functions in
md.fn[functionName](if you’ve registered custom functions) - Window functions in
window[functionName](any global function)
Example:
{ "c": "{{call.getCartTotal()}}", "o": "gte", "m": "100" }
{ "c": "{{call.getUserTier()}}", "o": "eq", "m": "premium" }
Function Requirements:
- Function must exist in
windowobject or be registered - Function must return a primitive type (string, number, boolean)
- Function is executed safely within the SDK context
Example Functions:
// Global functions (automatically available)
window.getCartTotal = function() {
return window.cart ? window.cart.total : 0;
};
window.getUserTier = function() {
return window.user ? window.user.tier : 'free';
};
Function Safety: Functions are validated and executed safely within the SDK context.
Lookup Tables
Lookup tables provide static and dynamic data mapping capabilities for complex filtering scenarios.
Static Tables (ts)
Static Key-Value Tables
Static tables provide direct key-value lookups for consistent data mapping.
Syntax: {{lookup.TABLE_NAME.KEY}}
{
"ts": {
"currencies": {
"DE": "EUR",
"US": "USD",
"GB": "GBP",
"FR": "EUR"
},
"regions": {
"DE": "Europe",
"US": "North America",
"GB": "Europe"
}
}
}
Usage in Filters:
{ "c": "{{lookup.currencies.{{data.country}}}}", "o": "eq", "m": "EUR" }
{ "c": "{{lookup.regions.{{data.country}}}}", "o": "eq", "m": "Europe" }
Nested Macros: Keys can contain macros that are resolved before lookup.
Regex Tables (tr)
Pattern-Based Tables
Regex tables use pattern matching to find the first matching key and return its value.
Syntax: {{lookupr.TABLE_NAME.KEY}}
{
"tr": {
"user_agents": {
".*Chrome.*": "chrome",
".*Firefox.*": "firefox",
".*Safari.*": "safari",
".*Mobile.*": "mobile"
},
"email_domains": {
".*@gmail\\.com$": "google",
".*@outlook\\.com$": "microsoft",
".*@yahoo\\.com$": "yahoo"
}
}
}
Usage in Filters:
{ "c": "{{lookupr.user_agents.{{window.BW_INFO.ua}}}}", "o": "eq", "m": "chrome" }
{ "c": "{{lookupr.email_domains.{{data.email}}}}", "o": "eq", "m": "google" }
Pattern Matching: First matching pattern wins, order matters.
Advanced Filter Features
Value Transformations
Custom Value Handling
Filters support multiple transformation options for handling different value states:
d: Default - Used when check result is empty/null. Example:"d": "free"cu: Custom undefined - Used when result isundefined. Example:"cu": "unknown"cn: Custom null - Used when result isnull. Example:"cn": "empty"ct: Custom true - Used when result is booleantrue. Example:"ct": "yes"cf: Custom false - Used when result is booleanfalse. Example:"cf": "no"
Example:
{
"c": "{{data.subscription}}",
"o": "eq",
"m": "active",
"d": "inactive",
"cu": "unknown",
"cn": "null"
}
String Formatting (f field):
| Format | Description | Purpose | Example |
|---|---|---|---|
lc | Lowercase | Transforms value to lowercase | "Hello" → "hello" |
uc | Uppercase | Transforms value to uppercase | "hello" → "HELLO" |
sc | Snake case | Converts spaces to underscores | "Hello World" → "hello_world" |
Practical Example:
{
"c": "{{data.user_type}}",
"o": "eq",
"m": "premium",
"f": "lc"
}
// If data.user_type = "PREMIUM", it gets transformed to "premium" before comparison
// The matching logic still compares "premium" == "premium"
Multiple Filters
Filter Arrays
Multiple filters can be combined using arrays. By default, ANY filter must pass for the action to execute (OR logic).
Example:
{
"filters": [
{ "c": "{{data.country}}", "o": "eq", "m": "DE" },
{ "c": "{{window.BW_INFO.t}}", "o": "eq", "m": "mobile" },
{ "c": "{{data.age}}", "o": "gte", "m": "18" }
]
}
How it works: The system uses .some() logic - if ANY filter in the array returns true, the action executes.
Practical Example:
{
"filters": [
{ "c": "{{data.country}}", "o": "eq", "m": "DE" }, // User from Germany
{ "c": "{{data.country}}", "o": "eq", "m": "FR" }, // OR User from France
{ "c": "{{data.country}}", "o": "eq", "m": "IT" } // OR User from Italy
]
}
// Action executes if user is from ANY of these countries
Note: There is no require_all_triggers option. The filtering system always uses OR logic for multiple filters.
Practical Examples
Understanding Data Limitations
What You CAN Filter On
// ✅ Available - Data set via SDK
{ "c": "{{data.user_segment}}", "o": "eq", "m": "premium" }
// ✅ Available - Browser information
{ "c": "{{window.BW_INFO.t}}", "o": "eq", "m": "mobile" }
// ✅ Available - URL parameters
{ "c": "{{url.searchParams.utm_source}}", "o": "eq", "m": "google" }
// ✅ Available - Custom variables
{ "c": "{{var.cart_total}}", "o": "gt", "m": "100" }
What You CANNOT Filter On
// ❌ Not available - Server-side data
{ "c": "{{server.user_purchase_history}}", "o": "gt", "m": "5" }
// ❌ Not available - Backend analytics
{ "c": "{{analytics.lifetime_value}}", "o": "gt", "m": "1000" }
// ❌ Not available - Complete user profile
{ "c": "{{profile.subscription_tier}}", "o": "eq", "m": "enterprise" }
// ❌ Not available - Historical data
{ "c": "{{history.last_login_days}}", "o": "lt", "m": "7" }
Workaround: Set relevant data via SDK methods before filtering:
// Set data that filters can access
Hood('setuserproperties', {
user_segment: 'premium',
subscription_tier: 'enterprise',
cart_total: window.cart?.total || 0
});
E-commerce Targeting
Cart Abandonment Recovery
Show a discount modal to users who added items to cart but haven’t completed checkout:
{
"triggers": [
{ "type": "beforeunload" }
],
"filters": [
{ "c": "{{call.getCartTotal()}}", "o": "gt", "m": "0" },
{ "c": "{{data.has_completed_checkout}}", "o": "isfalse" },
{ "c": "{{data.country}}", "o": "eq", "m": "DE" }
]
}
User Segmentation
Target premium users with exclusive offers:
{
"triggers": [
{ "type": "scroll", "config": { "vertical": 75 } }
],
"filters": [
{ "c": "{{data.user_tier}}", "o": "eq", "m": "premium" },
{ "c": "{{data.last_purchase}}", "o": "isset" },
{ "c": "{{lookup.regions.{{data.country}}}}", "o": "eq", "m": "Europe" }
]
}
Geographic Targeting
Location-Based Campaigns
Show region-specific content based on user location:
{
"triggers": [
{ "type": "load" }
],
"filters": [
{ "c": "{{lookup.currencies.{{data.country}}}}", "o": "eq", "m": "EUR" },
{ "c": "{{lookup.regions.{{data.country}}}}", "o": "eq", "m": "Europe" },
{ "c": "{{window.BW_INFO.ul}}", "o": "eq", "m": "en" }
]
}
Mobile-Specific Offers
Target mobile users with app download prompts:
{
"triggers": [
{ "type": "timer", "config": { "time": 10000 } }
],
"filters": [
{ "c": "{{window.BW_INFO.t}}", "o": "eq", "m": "mobile" },
{ "c": "{{data.has_app}}", "o": "isfalse" },
{ "c": "{{data.app_store_visits}}", "o": "lt", "m": "3" }
]
}
Behavioral Targeting
Engagement-Based Targeting
Show content based on user behavior patterns:
{
"triggers": [
{ "type": "scroll", "config": { "vertical": 90 } }
],
"filters": [
{ "c": "{{data.page_views}}", "o": "gte", "m": "5" },
{ "c": "{{data.time_on_site}}", "o": "gte", "m": "300" },
{ "c": "{{data.bounce_rate}}", "o": "lt", "m": "0.3" }
]
}
Return Visitor Targeting
Target returning users with personalized content:
{
"triggers": [
{ "type": "pageView" }
],
"filters": [
{ "c": "{{session.vt}}", "o": "isset" },
{ "c": "{{data.last_visit}}", "o": "gte", "m": "7" },
{ "c": "{{data.newsletter_subscribed}}", "o": "isfalse" }
]
}
Best Practices
Performance Optimization
Efficient Filtering
- Order filters by selectivity - Put most restrictive filters first
- Use appropriate operators -
issetis faster thaneqfor existence checks - Cache expensive operations - Use
var.*for computed values - Limit regex complexity - Keep regex patterns simple and safe
Example:
{
"filters": [
{ "c": "{{data.user_id}}", "o": "isset" }, // Fast existence check
{ "c": "{{data.country}}", "o": "eq", "m": "DE" }, // Simple equality
{ "c": "{{data.email}}", "o": "matchregex", "m": "^[^@]+@[^@]+\\.[^@]+$" } // Complex check last
]
}
Error Handling
Robust Filter Design
- Provide defaults - Use
d,cu,cnfields for missing data - Validate inputs - Test filters with various data states
- Handle edge cases - Consider null, undefined, and empty values
- Monitor performance - Watch for slow regex or complex lookups
Example:
{
"c": "{{data.user_segment}}",
"o": "eq",
"m": "premium",
"d": "free", // Default for empty values
"cu": "unknown", // Handle undefined
"cn": "null" // Handle null
}
Troubleshooting
Common Issues
Debugging Filters
Filter not matching:
- Check macro syntax:
{{data.property}}not{data.property} - Verify data exists: Use
issetoperator first - Test with simple values: Start with
eqoperator
Performance issues:
- Avoid complex regex patterns
- Limit nested macro calls
- Use
var.*for expensive computations
Data not available:
- Ensure data is set before filter evaluation
- Use
setuserpropertiesfor user data - Check browser compatibility for
window.*properties
Example Debug Filter:
{
"c": "{{data.debug_info}}",
"o": "eq",
"m": "{{data.user_id}}",
"d": "no_user_id",
"cu": "no_data",
"cn": "null_data"
}