Docs
Features
Custom Properties

Custom Properties

Overview

Custom properties lets you combine existing properties into new properties on the fly, using a simple Excel-like formula language. You can then use these new properties almost anywhere that you can use regular properties, with the ability to save/share them for reuse across your team. For more on why we built this, check out our blog (opens in a new tab).

Use Cases

Grouping Marketing Channels

If you're a marketer, using Mixpanel to show the impact of various channels on acquisition, you might want to group your UTM Sources into higher level buckets. For example:

  • Facebook, Instagram, Twitter → Social
  • Google, Bing → Search
  • Everything else → Organic

You can also use the Channel Classifier template in custom properties as a starting point.

image

Compute Properties Mathematically from Other Properties

If you have an e-commerce app, you can combine "price" and "quantity" properties into a "total price" property as follows:

image

Compute the Number of Days Between Two Date Properties

Use custom properties to compute the date/time difference between two date properties. You can also use the special "TODAY()" function to find the difference between a date property and the current date/time. This is ideal when you want to transform a "DateofBirth" property into “age” or a "Created" property into “days active since registration”.

A new custom property can be defined by taking into account the “Created” property and using the following transformation:

image

Compare Different Properties

Use custom properties to create a new property if two property values are the same.

For example:

A company wants to find out what percentage of purchases are being made by users that have changed countries since sign up.

They can create a custom property to determine whether the two country values are the same with this transformation:

image

Extract Domain from Email Address

Extract the domain of the email from an email address. You can parse out parts of a string after "@" using the SPLIT function:

image

Query a List with an Index

Let’s say you have a list of recommendations as a property, and you’d like to parse out the first recommendation as another string property.

You can parse out the first delivery ID in a list property with several DeliveryIDs:

image

The same syntax works with objects.

Borrow properties from one event onto subsequent events

image

For events that cannot have certain properties easily tracked, borrowed properties comes into the picture. This functionality allows you to borrow the specific property from a preceding action

image

Some scenarios where this functionality could be used:

  • When merging events from 2 different systems, like server side & client side: Use Case: You want to know transactions processed (which is a server side event), broken down by restaurant category (which is a property on a client side event order placed)
  • When one team/ app wants to leverage tracking from 2+ teams/ apps: Use Case: You want to know whether launch of Dark Mode, driven by the central team, impacted overall time spent on the page, which is your core KPI. Instead of adding the property - dark mode setting onto all the page view events, you can borrow this from existing tracking setup by the central launch team (dark mode toggle event)
  • When wanting to join event properties within a product session: Use Case: You want to know which in product banners led to most purchase conversions

Creating a Custom Property

Click the plus button to the right of the search bar, then select Event Property or User Property to open the property builder.

image

Optionally give your property a name and click into the formula bar to start defining it. If you're new to this feature, we recommend starting with one of the examples. Click the Insert Example drop down to populate the box with a use-case specific custom property.

When writing your formula, click Ctrl + Space to see a list of all the available functions and their descriptions. Click period (.) to search for event or user profile properties to add to the formula.

image

Custom properties are local to the report by default, when you select Apply. To save the custom property permanently for use in other reports and to make it usable by other project members, click Save. We recommend Apply-ing the custom property and using it in your local analysis first, before saving and sharing, to reduce clutter in the project.

When you create custom properties and select Save as Custom Property, your created custom property will be private by default. You can also add a description at this stage, so you and your colleagues can know what the custom property is for. You can also decide to save the custom property and share that custom property with specific colleagues, teams or the entire organization by clicking "Save and Share":

Also note that the formula used to compose your custom property can't be longer than 20,000 characters.

Reference

Functions

Use the following functions in the Formula field to modify your custom property:

FunctionDefinitionSyntax & Example
ifEvaluates if an expression is true or false.if(condition, value if true, value if false)

Example:
if(A=="Facebook" or A=="Twitter", "Social", A)
ifsRuns multiple checks and returns a value corresponding to the first true result. If no conditions are true, undefined is returned.ifs(condition1, value1, condition2, value2, …)

Example:
ifs( A<60,"Less than 1 hour",
A<120, "More than 1 hour but less than 2 hours",
A>=120, "More than 2 hours")
notReturns values that are not true.not(condition)

Example:
not(A == "Facebook")
andReturns true if both conditions are met. Else, returns false.x and y

Example:
if(A=="San Francisco" and B=="Chrome", "Valid user", "Invalid User")
orReturns true if either condition is met. Else, returns false.x or y

Example:
if(A=="San Francisco" or B=="Chrome", "Valid user", "Invalid User")
inReturns true if the first condition is contained in the second condition.x in condition

Example:
if("Facebook" in A, "Facebook Corporation", A)

This can also be used to check against a list of values:
if(A in ["Chrome","Firefox","Edge"],"Acceptable browser","Unsupported browser")
booleanCasts the argument to a boolean.boolean(value)->false, boolean(alternate value)-> true

Example:
boolean(A)
numberCasts the argument to a number.number(value to cast)

Example:
number(A)
stringCasts the argument to a string.string(value to cast)

Example:
string(A)
definedDetermines if a value exists. If a property is not defined on a parent event or profile, this will return false, otherwise this will return true.defined(variable to check for existence)

Example:
defined(A)
has_prefixDetermines whether a string starts with another string. This comparison is case-insensitive.has_prefix(string to check, prefix)

Example:
has_prefix(A, "United")
has_suffixDetermines whether a string ends with another string. This comparison is case-insensitive.has_suffix(string to check, suffix)

Example:
has_suffix(A,"States")
minDetermines the minimum value between two numbers.min(number, number)

Example:
min(A,B)
maxDetermines the maximum value between two numbers.max(number, number)

Example:
max(A,B)
floorReturns the largest integer that is smaller than or equal to the input (ie: rounds down to the nearest integer).floor(number)

Example:
floor(A)
ceilReturns the smallest integer value greater than or equal to the input (ie: rounds up to the nearest integer).ceil(number)

Example:
ceil(A)
roundReturns the nearest integer value of the input value.round(number)

Example:
round(A)
upperCast string property values to uppercase.upper(string property)

Example:
upper(A); upper("hello") -> "HELLO"
lowerCast string property values to lowercase.lower(string property)

Example:
lower(A); lower("FacEBook") -> "facebook"
parse_url()Extracts the part of the url that is specified: domain(google) or full_domain(google.co.uk)parse_url(string property, part of url)

Example: parse_url(A,"domain")
regex_extractIf haystack is a string and pattern matches at least one substring, extracts the result from the first pattern match in haystack. The result is a string equal to the entire regex match, or if capture group is specified, only that portion of the match.regex_extract(haystack, pattern, <optional capture group#>)

Example:
regex_extract("iPhone5.1","iPhone(...)",1) ->5.1
regex_matchReturns true if the pattern matches any part of the string.regex_match(haystack, pattern)

Example:
regex_match("zzhaystackzz", "ha(..)ack") -> true
// Use (?-i) for case-sensitive matching: regex_match("HAYSTACK", "(?-i)haystack") -> false
regex_replaceReplaces the parts of a string that match a regular expression with a different string.regex_replace(haystack, pattern, replacement)

Example:
// convert currency string to number: regex_replace("$1,234,567", "[^.0-9]\*", "")) -> 1234567
datedifSubtract two dates. Units:
D: days.
M: months.
Y: years
MD: days remaining after subtracting whole months.
YM: months remaining after subtracting whole years.
YD: days, assuming start_date and end_date are within 1 year.
Use TODAY() for current day.

datedif(start_date,end_date,unit)

Example:
datedif(registrationdate,TODAY(), "M") -> 5
lenReturns the length of the string or the list.len(string) or len(list)

Example:
len("Canada") -> 6
leftReturns characters from the beginning of a given string.left(string, num_of_characters)

Example:
left("Canada",3) -> "Can"
rightReturns characters from the end of a given stringright(string, num_of_characters)

Example:
right("Canada",3) -> "ada"
midReturns characters from the middle of a given stringmid(string, first_index, num_of_characters)

Example:
mid("Canada",1,4) -> "Cana"
splitSplits a string into different parts based on a user-specified delimiter, and lets you select a particular split. Delimiter must be a single ASCII character. To fetch a list of all splits, don't pass a third argument. The first split is accessible by passing n=1 (second with n=2, ...)split(input string, delimiter, [n: optional]) → string

Examples with 1 split:
split("dwight@dm.com","@",2) -> "dm.com"
split("dwight@dm.com","@",4) -> undefined
split("dwight@dm.com","/",2) -> dwight@dm.com
split("empty//string/","/",2) -> ""

Examples with all splits:
split("dwight@dm.com","@") -> ["dwight", "dm.com"]
split("a/b/c/d", "/") -> ["a", "b", "c", "d"]
split("a/b/c/d", "-") -> ["a/b/c/d"]
split("a//b/c/d", "/") -> ["a", "", "b", "c", "d"]
letDefine a variable and use it in an expression. This helps keep the custom property definition neat and non-repetitive. Variables are only active within the scope of the LET function. You can nest multiple let functions to define multiple variables.let(name, definition, expression)

// define a variable "spend" and use it in an expression let( spend, <price> * <quantity>, ifs( spend < 50, "no discount", spend < 200, "gold discount", spend > 200, "platinum discount", TRUE, "invalid" ) )
Note: <price> and <quantity> are event properties.
anyEvaluates to TRUE if the given expression is true for any value in the given list. The expression can refer to the current list element by the given name.any(name, list, expr)

Example:
Let's say you had a list of numbers called priceList= [5,205,178,12,22]
any(X, priceList, X > 300) -> false.
any(X, priceList, X >= 5 and X < 300) -> true.
allEvaluates to TRUE if the given expression is true for all values in the given list. The expression can refer to the current list element by the given name.all(name, list, expr)

Example:
Let's say you had a list of numbers called priceList= [5,205,178,12,22]
all(X, priceList, X > 5 and X < 200) -> false.
all(X, priceList, X >= 5 and X < 300) -> true.
filterFilters the given list to only include items for which the given expression is true. The expression can refer to the current list element by the given name.filter(name, list, expr)

Example:
Let's say you had a list of numbers called priceList= [5,205,178,12,22]
filter(X, priceList, X>100) -> new shortened list = [205,178]
mapTransforms each value in the given list using the given expression. The expression can refer to the current list element by the given name.map(name, list, expr)

Example:
Let's say you had a list of states = ["Georgia","Florida","Texas"]
map(X, states, lower(X)) -> ["georgia","florida","texas"]
sumSums all numbers in the given list. Non-numeric items in the list are ignored.sum(list)

Example:
Let's say you had a list of numbers called priceList= [5,205,178,12,22]
sum(priceList) -> 422.

sum(filter(X, priceList, X>100)) -> 383, because filter(X,priceList, X>100) -> [205,178] and sum([205,178]) -> 383.

Numeric Operators

Use the following numeric operators in the Formula field to modify your custom property using:

  • +: Addition. Can also be used to create a concatenation.
  • -: Subtraction
  • *: Multiplication
  • /: Division
  • %: Modulo

Comparison Operators

Use the following comparison operators in the Formula field to modify your custom property:

  • <: The first number is strictly less than the second number.
  • >: The first number is strictly greater than the second number.
  • >=: The first number is greater than or equal to the second number.
  • <=: The first number is less than or equal to the second number.
  • ==: The first argument is equal to the second argument. If both arguments are strings, the comparison is case-insensitive.
  • !=: The first argument is not equal to the second argument. If both arguments are strings, the comparison is case-insensitive.

Constants

  • false: Represents the literal value of boolean false.
  • true: Represents the literal value of boolean true.
  • undefined: Represents the literal value of cases that aren’t defined.

Borrowed Properties

How to create a borrowed property is demonstrated in this video

Some key notes

  • Borrowed property creation is limited to Admin & Owner Roles only
  • A project can have a maximum of 20 borrowed properties. Hence you are encouraged to only create borrowed properties useful to the larger team
  • A borrowed property once created is like any other custom property. It can be accessed by all in the project depending on permissions
  • Borrowing of a property is strictly from the most recent event in the 7 day lookback window. To elaborate
    • Say on event “purchase”, you want to borrow property “search term” from an event “search product”. If there are multiple events “search product” before “purchase”, the property will be borrowed from the most recent “search product” event where the property is set.
    • Lookback is also fixed to a 7 day window. Say the “purchase” event occurred on 31st Jan, if the most recent “search product” occurred on 20th Jan, the borrow functionality will return “search term” = (not set), since this event happened 11 days ago which is outside the lookback window range.

Was this page useful?