Best practice creating KPIs :
Ensure KPIs have simple, intuitive names that are easy to understand at a glance. Avoid jargon.
Add brief descriptions for KPIs that require additional clarification. This ensures everyone understands the data's purpose and scope.
Incorporate appropriate suffixes or units, such as
/5for ratings,%for percentages, or$for monetary values.
Understanding the Formula Builder
The formula builder lets you create custom KPIs using three main components:
Functions: Define the metric you want to measure.
Example:feedback()Parameters: Narrow the scope of the metric.
Example:"import.type", "=", "trustpilot"Properties: Specify detailed attributes using dot notation.
Example:"import.type", "=", "trustpilot"
➡️ Combine all of them to reach a formula:
function("parameter_name.property", "=", "parameter_value") ⚠️ Adding " " around each value is mandatory for the formula to work.
1. Functions
feedback()
Count of feedbacks
Parameters | Custom Formula | Result |
import.type | feedback("import.type", "=", "google_review") | Count of feedback imported from Google Reviews. |
team.id | feedback("team.id", "=", "9921") | Count of feedback that matches a single team.
Count of feedback that matches multiple teams. |
segment.id | feedback("segment.id","=","1234") | Count of feedback that matches a single segment.
Count of feedback that matches multiple segments
|
survey.id | feedback("survey.id", "=", "1526") | Count of feedback that matches a single survey. |
question.type | feedback("question.type", "=", "nps") | Count of feedback that includes NPS questions. |
question.id | feedback("question.id", "=", "1526") | Count of feedback that are having the question 1526. |
question.name | feedback("question.name", "=", "Tell us more") | Count of feedback that matches a question by name. |
question.option_id | feedback("question.option_id", "=", "1234") | Count of feedback that matches the specific choice or rating table option. |
question.option_name | feedback("question.option_name", "=", "experience") | Count of feedback that matches the specific label of a choice or rating table option |
topic.name | feedback("topic.name", "=", "shipping cost") | Count of feedback that matches a specific topic name |
attribute.id | feedback("attribute.id", "=", "1232:male") | Count of feedback that matches the value ‘male’ by id |
attribute.name | feedback("attribute.name", "=", "city") | Count of feedback that matches a specific attribute by name or with a value |
feedback.id | feedback("feedback.id", "=", "2312") | Count of feedback that matches a specific feedback by id |
feedback.type | feedback("feedback.type", "=", "completed") | Count of feedback that has either been complete or incomplete. |
push.canal
| feedback("push.canal", "=", "sms") | Count of feedback that matches whether feedback pushes were email or sms |
push.status List of status here. | feedback("push.status", "=", ["clicked", "opened"]) | Count of feedback that matches the status of pushes |
nps.profile
| feedback("nps.profile", "=", "promoter") | Count of promoter feedbacks |
push()
Count of sent emails and SMS
Parameters | Custom Formula | Result |
push.canal
| feedback("push.canal", "=", "sms") | Count of pushes that matches the canal. |
push.status | push("push.status", "=", "bounced") | Count of pushes that matches the status of push. |
push.includeFollowUps | push("push.includeFollowUps","=",true,"push.status","=",["scheduled","requested"]) | Count of ALL pushes including followups. |
nps()
Net Promoter Score = % Promoters - % Detractors
Parameters | Custom Formula | Result |
import.type | nps("import.type", "=", "csv") | NPS score of all feedbacks imported via CSV files. |
team.id | nps("team.id", "=", "9921") | NPS score of specific team. |
segment.id | nps("segment.id", "=", "111") | NPS score based on this particular segment of feedback. |
survey.id | nps("survey.id", "=", "11") | NPS score of specific survey. |
question.name
The name must correspond to an NPS question type | nps("question.name", "=", "On a scale from 0 to 10, how likely are you to recommend us to a friend or colleague?") | NPS score of specific question name. |
question.id
The question id must correspond to an NPS question type | nps("question.id", "=", "11") | NPS score of feedbacks having this specific question. |
feedback.type
| nps("feedback.type", "=", "completed") | NPS score of completed feedbacks |
nps.profile | nps("nps.profile", "=", "detractor") | NPS score of detractor feedbacks |
sentiment()
Sentiment score
Parameters | Custom Formula | Result |
import.type | sentiment("import.type", "=", "csv") | Sentiment score of all feedbacks imported via CSV files. |
team.id | sentiment("team.id", "=", "9921") | Sentiment score of specific team. |
segment.id | sentiment("segment.id", "=", "111") | Sentiment score based on this particular segment of feedback. |
survey.id | sentiment("survey.id", "=", "11") | Sentiment score based on this particular survey. |
topic.name | sentiment("topic.name", "=", "Packaging") | Sentiment score of the entire feedbacks having the topic “Packaging” attached
Sentiment score of the text item within feedbacks having the topic “Packaging“ attached
Sentiment score of feedbacks not having the topic “Packaging” attached
Sentiment score of the feedbacks without counting the sentiment of verbatims having the topic Packaging attached |
question.name | sentiment("question.name", "=", "What did you find most challenging?") | Sentiment score of the entire feedbacks having the question"What did you find most challenging?"
Sentiment score of the specific question What did you find most challenging?" in all feedbacks
Sentiment score of the entire feedbacks not having the question"What did you find most challenging?"
Sentiment score of the entire feedbacks without counting the sentiment of the question "What did you find most challenging?" |
question.id The question id must be a text item | sentiment("question.id", "=", "11") | Sentiment score of feedbacks having this question id |
feedback.type | sentiment("feedback.type", "=", "completed") | Sentiment score of completed feedbacks. |
nps.profile | sentiment("nps.profile", "=", "detractor") | Sentiment score of detractor feedbacks. |
satisfaction()
Satisfaction ratio
Parameters | Custom Formula | Result |
import.type | satisfaction("import.type", "=", "csv") | Satisfaction score of all feedbacks imported via CSV files. |
team.id | satisfaction("team.id", "=", "9921") | Satisfaction score of specific team. |
segment.id | satisfaction("segment.id", "=", "111") | Satisfaction score based on this particular segment of feedback. |
survey.id | satisfaction("survey.id", "=", "11") | Satisfaction score based on this particular survey. |
topic.name | satisfaction("topic.name", "=", "Packaging") | Satisfaction score of the entire feedbacks having the topic “Packaging” attached
Satisfaction score of the text item within feedbacks having the topic “Packaging“ attached
Satisfaction score of feedbacks not having the topic “Packaging” attached
Satisfaction score of the feedbacks without counting the sentiment of verbatims having the topic Packaging attached |
question.name | satisfaction("question.name", "=", "What did you find most challenging?") | Satisfaction score of the entire feedbacks having the question"What did you find most challenging?"
|
question.id The question id must be a text item | satisfaction("question.id", "=", "11") | Satisfaction score of feedbacks having this question id |
feedback.type | satisfaction("feedback.type", "=", "completed") | Satisfaction score of completed feedbacks. |
nps.profile | satisfaction("nps.profile", "=", "detractor") | Satisfaction score of detractor feedbacks. |
ces()
Customer Effort Score
Parameters | Custom Formula | Result |
import.type
team.id
segment.id
survey.id
topic.name
attribute.id
attribute.name
question.type=ces
question.name=name of a ces question
question.id(if it has a CES question)
feedback.type(if it has a CES question) | ces("topic.name", "=", "delivery") | Customer effort score based on this particular topic. |
ratings()
single rating questions only
Parameters | Custom Formula | Result |
import.type
team.id
segment.id
survey.id
topic.name
attribute.id
attribute.name
question.type=ces
question.name=name of a ces question
question.id(if it has a CES question)
feedback.type(if it has a CES question) | ratings("attribute.name", "=", "gender:female") | Average rating score based on those that have an attribute name collected that corresponds to ‘gender’ and is female |
ratingsTable()
multiple rating question options
Parameters | Custom Formula | Result |
import.type
team.id
segment.id
survey.id
topic.name
attribute.id
attribute.name
question.type=ratingsTable
question.name=name of a ratingsTable question
question.id(if it has a Ratings Table question)
feedback.type(if it has a Ratings Table question) | ratingsTable(“question.type", "=", "nps") | Average rating table score based on feedback that also has collected nps. |
url()
Create a new custom API call that returns the value located with Dot Notation Value.
Parameters | Custom Formula | Result |
*This is a special case where only a link can be added to this function
"url.{dot-notation-value}" | url("link.link", "=", "http://google.com") | This would pick up a data point linked to the url chosen. |
volume()
count of a given parameter
Parameters | Custom Formula | Result |
survey.id(count of questions)
question.type(count of question type)
attribute.id(count of attribute values)
attribute.name(count of attribute values) | volume("attribute.name", "=", "country:Poland") | Total count of times the attribute country = Poland was recorded on the platform |
response()
count of a given parameter
Parameters | Custom Formula | Result |
import.type
team.id
segment.id
survey.id
topic.name
attribute.id
attribute.name
question.id
feedback.type
questions.type=ratings
questions.name=
response.value | response("feedback.type", "=", "incomplete","question.type","=","textarea")
response("question.id", "=", "11111")
response("question.id", "==", "11111")
response("response.value","==","5","question.option_name","===","Petit déjeuner ")
| Count the number of answers in the feedback where the feedback was not fully complete.
Count the number of answers in the feedback where the question 11111 exists
Count the number of answers specifically related to question 11111
Count the number of answers of a rating question where the rating question option for Petit déjeuner is 5. |
time()
Parameters | Custom Formula | Result |
import.type
team.id
segment.id
survey.id
topic.name
attribute.id
attribute.name
question.id
feedback.type
questions.type
questions.name
response.value | time("survey.id", "=", "1324")
| Total time it takes to complete survey with id 1324 |
financial()
financial count of revenue at risk
Parameters | Custom Formula | Result |
financial.type | financial("financial.type", "=", "risk")
| Financial count of revenue at risk |
resolutionTime()
Total time it takes to resolve feedbacks from the feedback creation date to the status is “resolved”
Parameters | Custom Formula | Result |
import.type
team.id
segment.id
survey.id
topic.name
attribute.id
attribute.name
question.id
feedback.type
questions.type=ratings
questions.name=
response.value | resolutionTime("survey.id", "=", "1324")
| Total time it takes to resolve feedbacks from the feedback creation date to the status is “resolved” for survey with id 1324
The resolutionTime is in seconds make sure to adapt it to your needs:
|
2. Properties
Our properties come after a dot and allow users to further define which type of parameters value they want to add
Property | Description | Variables |
.name | the value of the parameter will be a name | - |
.type | the value of the parameter will be a type | - |
.id | the value of the parameter will be an id number | - |
.{url) | Only available for the url function | - |
import.type | used to link with an import method. | survey |
question.type | the type of question you want to select | nps |
feedback.type | whether the feedback was completely finished or left incomplete. | completed incomplete |
push.canal | whether the call for feedback was an email or sms | email |
push.status | what the status of the push is that you’d like to track | scheduled |
nps.profile | the profile of the feedback | promoter detractor neutral |
financial.type | the type of financial impact the feedback has depending if it’s positive or negative. | risk opportunity
|
3. Parameters
Operator | Scope | Description |
| Whole Feedback 📦 | Targets the entire feedback and applies the condition at feedback level. |
| Feedback Item 🎯 | Targets specific feedback item data (question, rating, field). |
| Whole Feedback 🚫 | Excludes feedback where the feedback-level value matches the condition. |
| Feedback Item 🎯 | Excludes feedback where a specific feedback item matches the condition. |
What are the most used custom KPIs ?
The Response Rate :
feedback()/push()*100
Response rate of a particular score, you can use the following :
response("response.value", "=", [3,4,5], "question.id", "=", "123274")/feedback("question.id", "=", "123274")*100
Ratio of feedback imported on Google :
(feedback("import.type", "=", "google_review") / feedback("import.type", "=", "all")) * 100
Average CSAT for all rating questions :
(feedback("response.value","=",[4,5],"question.type","=","slider")/feedback("question.type","=","slider"))*100
Percentage of those that answered 'a' for all choice questions :
feedback("question.option_name","=","a")/feedback("question.type","=","select")*100
Detractor Percentage :
feedback("nps.profile","=","detractor")/(feedback("nps.profile","=","promoter")+feedback("nps.profile","=","passive")+feedback("nps.profile","=","detractor"))
Promoter Percentage :
feedback("nps.profile","=","promoter")/(feedback("nps.profile","=","promoter")+feedback("nps.profile","=","passive")+feedback("nps.profile","=","detractor"))