This guide is intended for advanced Natterbox admins. Further customisations of this solution might not be supported.
Overview
While standard IVR components are limited to single-digit (1–9) inputs, using a Lua Script component allows you to capture a full 1–10 range. This guide walks through a 3-question survey flow that stores results into unique variables for reporting.
This guide is designed to be used in conjunction with our Post-Call Survey Guide, replacing the standard IVR digit capture with a more flexible script.
.png?sv=2022-11-02&spr=https&st=2026-02-04T22%3A04%3A19Z&se=2026-02-04T22%3A22%3A19Z&sr=c&sp=r&sig=MACnZm%2Fm4NPWDxmDGzqT%2B5%2BKB9i9foE1irHblhpxynk%3D)
Why use Lua for CSAT?
Feature | Standard IVR | Lua Script |
|---|---|---|
Numeric Range | 1-9 (Single Digit) | 1-10+ (Multi-digit) |
Input Validation | Limited | High (RegEx patterns) |
Error Handling | Basic | Advanced (Custom retry logic) |
User Experience | Requires immediate input | Allows for |
Step 1: The Introductory Speech
Begin your survey policy with a Speak component to set expectations.
The voice from the known repertoire: English (GB): Kate (This can be configured to any voice that suits your requirements but make sure this matches the same voice configured in the LUA script components)
The phrase you want to say: "To better improve our service, please stay on the line after the call for a brief 3-question survey."
Purpose: This reduces "hang-up" rates by informing the caller that the survey is short and how many questions to expect.
.png?sv=2022-11-02&spr=https&st=2026-02-04T22%3A04%3A19Z&se=2026-02-04T22%3A22%3A19Z&sr=c&sp=r&sig=MACnZm%2Fm4NPWDxmDGzqT%2B5%2BKB9i9foE1irHblhpxynk%3D)
Step 2: The Script Template
Copy and paste this code into each component, ensuring you update the Prompt Text and the Variable Name (e.g., NPS_Result, NPS_Result2) for each question.
enable_debug('email')
function ask_nps_question()
local ivr = {}
ivr[1] = {}
ivr[1].name = 'Score'
ivr[1].pattern = '^([1-9]|10)#$' -- Validates 1-9 or 10 followed by #
local attempts, max_attempts, res = 0, 3, nil
while res == nil and attempts < max_attempts do
-- UPDATE THE QUESTION TEXT BELOW
res = session.ivr(ivr, "On a scale of 1 to 10, how would you rate this call? Please enter the number followed by the hash key.", 'EN_KATE', 5000)
if res == nil then
attempts = attempts + 1
if attempts < max_attempts then
session.say("I'm sorry, I didn't recognize that score. Please enter a number between 1 and 10 followed by the hash key.", 'EN_KATE')
end
end
end
return res and res['value'] or nil
end
local score = ask_nps_question()
if score then
-- UPDATE THE VARIABLE NAME BELOW (e.g., NPS_Result, NPS_Result2, NPS_Result3)
session.set('NPS_Result', score)
session.say("Thank you for your feedback.", 'EN_KATE')
return true
else
session.set('NPS_Result', 'No Input')
return false
endStep 3: Implementing the Lua Questions
You will add three Lua Script components in a row. Each script handles a specific question and saves the result to a unique session variable.
Question 1: Call Rating
Drag in a Lua component and paste the script below. Note the use of NPS_Result as the variable name.
Prompt: "On a scale of 1 to 10, how would you rate this call?"
.png?sv=2022-11-02&spr=https&st=2026-02-04T22%3A04%3A19Z&se=2026-02-04T22%3A22%3A19Z&sr=c&sp=r&sig=MACnZm%2Fm4NPWDxmDGzqT%2B5%2BKB9i9foE1irHblhpxynk%3D)
Question 2: Agent Rating
Drag in a second Lua component. Crucial: Change the variable name to NPS_Result2 and update the session.ivr(ivr, "On a scale of 1 to 10, how would you rate this call? Please enter the number followed by the hash key." message to reflect the new prompt below:
Prompt: "On a scale of 1 to 10, how would you rate the agent?"
.png?sv=2022-11-02&spr=https&st=2026-02-04T22%3A04%3A19Z&se=2026-02-04T22%3A22%3A19Z&sr=c&sp=r&sig=MACnZm%2Fm4NPWDxmDGzqT%2B5%2BKB9i9foE1irHblhpxynk%3D)
Question 3: Service Rating
Drag in a third Lua component. Crucial: Change the variable name to NPS_Result3 and update the session.ivr(ivr, "On a scale of 1 to 10, how would you rate this call? Please enter the number followed by the hash key." message to reflect the new prompt below:
Prompt: "On a scale of 1 to 10, how would you rate the service?"
.png?sv=2022-11-02&spr=https&st=2026-02-04T22%3A04%3A19Z&se=2026-02-04T22%3A22%3A19Z&sr=c&sp=r&sig=MACnZm%2Fm4NPWDxmDGzqT%2B5%2BKB9i9foE1irHblhpxynk%3D)
Please see below all scripts used in this policy below:
-- Enable debug to track the script execution in Natterbox logs
enable_debug('email')
-- Function to handle the looping question logic
function ask_nps_question()
local ivr = {}
-- Configure the expected input pattern
ivr[1] = {}
ivr[1].name = 'Score'
-- Matches any single digit 1-9 OR the number 10, followed by the hash key
ivr[1].pattern = '^([1-9]|10)#$'
local attempts = 0
local max_attempts = 3
local res = nil
-- Loop until valid input is received or max attempts are reached
while res == nil and attempts < max_attempts do
-- Prompt the user (Using voice EN_KATE)
res = session.ivr(ivr, "On a scale of 1 to 10, how would you rate this call? Please enter the number followed by the hash key.", 'EN_KATE', 5000)
if res == nil then
attempts = attempts + 1
if attempts < max_attempts then
session.say("I'm sorry, I didn't recognize that score. Please enter a number between 1 and 10 followed by the hash key.", 'EN_KATE')
end
end
end
-- Return the value if match found, or nil if timed out
if res ~= nil then
return res['value']
else
return nil
end
end
-- --- Main Execution ---
local score = ask_nps_question()
if score then
-- Store the valid input into a session variable.
-- This creates a macro available in the Dial Plan as $(Custom_NPS_Result)
session.set('NPS_Result', score)
session.say("Thank you for your feedback.", 'EN_KATE')
return true
else
-- Handle case where user did not provide valid input
session.set('NPS_Result', 'No Input')
return false
end--continue your script here
-- Enable debug to track the script execution in Natterbox logs
enable_debug('email')
-- Function to handle the looping question logic
function ask_nps_question()
local ivr = {}
-- Configure the expected input pattern
ivr[1] = {}
ivr[1].name = 'Score'
-- Matches any single digit 1-9 OR the number 10, followed by the hash key
ivr[1].pattern = '^([1-9]|10)#$'
local attempts = 0
local max_attempts = 3
local res = nil
-- Loop until valid input is received or max attempts are reached
while res == nil and attempts < max_attempts do
-- Prompt the user (Using voice EN_KATE)
res = session.ivr(ivr, "On a scale of 1 to 10, how would you rate the agent? Please enter the number followed by the hash key.", 'EN_KATE', 5000)
if res == nil then
attempts = attempts + 1
if attempts < max_attempts then
session.say("I'm sorry, I didn't recognize that score. Please enter a number between 1 and 10 followed by the hash key.", 'EN_KATE')
end
end
end
-- Return the value if match found, or nil if timed out
if res ~= nil then
return res['value']
else
return nil
end
end
-- --- Main Execution ---
local score = ask_nps_question()
if score then
-- Store the valid input into a session variable.
-- This creates a macro available in the Dial Plan as $(Custom_NPS_Result2)
session.set('NPS_Result2', score)
session.say("Thank you for your feedback.", 'EN_KATE')
return true
else
-- Handle case where user did not provide valid input
session.set('NPS_Result2', 'No Input')
return false
end-- Enable debug to track the script execution in Natterbox logs
enable_debug('email')
-- Function to handle the looping question logic
function ask_nps_question()
local ivr = {}
-- Configure the expected input pattern
ivr[1] = {}
ivr[1].name = 'Score'
-- Matches any single digit 1-9 OR the number 10, followed by the hash key
ivr[1].pattern = '^([1-9]|10)#$'
local attempts = 0
local max_attempts = 3
local res = nil
-- Loop until valid input is received or max attempts are reached
while res == nil and attempts < max_attempts do
-- Prompt the user (Using voice EN_KATE)
res = session.ivr(ivr, "On a scale of 1 to 10, how would you rate the service? Please enter the number followed by the hash key.", 'EN_KATE', 5000)
if res == nil then
attempts = attempts + 1
if attempts < max_attempts then
session.say("I'm sorry, I didn't recognize that score. Please enter a number between 1 and 10 followed by the hash key.", 'EN_KATE')
end
end
end
-- Return the value if match found, or nil if timed out
if res ~= nil then
return res['value']
else
return nil
end
end
-- --- Main Execution ---
local score = ask_nps_question()
if score then
-- Store the valid input into a session variable.
-- This creates a macro available in the Dial Plan as $(Custom_NPS_Result3)
session.set('NPS_Result3', score)
session.say("Thank you for your feedback.", 'EN_KATE')
return true
else
-- Handle case where user did not provide valid input
session.set('NPS_Result3', 'No Input')
return false
endStep 4: Closing & Detailed Feedback
After the third Lua component, route the call to a Switchboard to offer the caller a chance to leave detailed verbal feedback.
Message: "Thank you for your response. If you would like to leave a recording with more details about your experience, please press 1. If you would like to end the call, please press 2."
Option 1: Route to a Voicemail component to capture the verbal feedback.
Option 2: Route to a Finish component to hang up.
.png?sv=2022-11-02&spr=https&st=2026-02-04T22%3A04%3A19Z&se=2026-02-04T22%3A22%3A19Z&sr=c&sp=r&sig=MACnZm%2Fm4NPWDxmDGzqT%2B5%2BKB9i9foE1irHblhpxynk%3D)
Step 5: Salesforce Field Mapping (Reporting Gates)
Once your Lua scripts have captured the scores into session macros, you must map these values to Salesforce fields. This ensures that every survey response is recorded against the call log for historical reporting and dashboarding. Please refer to Reporting Gates guide on how to capture results within the Call Reporting Object as shown below:
.png?sv=2022-11-02&spr=https&st=2026-02-04T22%3A04%3A19Z&se=2026-02-04T22%3A22%3A19Z&sr=c&sp=r&sig=MACnZm%2Fm4NPWDxmDGzqT%2B5%2BKB9i9foE1irHblhpxynk%3D)