Workflow helpers

Use helpers to customize and enhance your workflows.
  • Understand workflow helpers

    As you build out the steps and logic of a workflow, you may need certain actions to perform advanced or dynamic functions. For example, you may want to address a customer by their name in the body of an email, check if a text message arrived within business hours before sending an auto-response, or reformat data received from a webhook entirely. Workflow helpers make this custom functionality possible by automating tasks and adding flexibility to your workflows through action and condition steps.Who can access this feature?User typesAdmins can access the Workflows page.In this articleAvailable helpers by groupHelper typesUse helpers in workflow data fieldsEscape sequencesAvailable helpers by groupKustomer provides various types of helpers to help you customize your workflows.Conditional helpersPerform actions and generate content based on the value of an attribute. Learn moreDate & math helpersGenerate and manipulate date objects, and perform arithmetic functions and number formatting. Learn moreString modification helpersManipulate strings of text. Learn moreJSON data helpersFormat and extract information from JSON data. Learn moreData validation helpersVerify and reformat data. Learn moreHelper typesExpression helpers are a common type of helper which appear wrapped in double or triple handlebars, and output a string of text. For example, {{randomId}}.Block helpers are a special type of helper that use multiple expression blocks and also output a string. They are defined with an opening block (an expression marked by a hash symbol, #), and a closing block (a second expression using a forward-slash, /). The desired output string will typically be constructed between the opening and closing blocks. For example, {{#if true}}Hello {{steps.1.name}}{{/if}}.Function helpers take on a different syntax, foregoing handlebars completely. These helpers are initiated with a workflow function command (/#fn:), and are capable of outputting both string and non-string data types. For example, /#fn:inBusinessHours.Note: Function helpers cannot nest or be nested in other helpers.Use helpers in workflow data fieldsIn code view, standard workflow step input fields directly accept a value of the field's stated attribute value-type. They also accept any handlebars expression or workflow command.However, a handful of input fields are designed as data fields, such as "meta", "data", "headers", "input", "error", and more. These input fields are distinct in that they use code-line numbers, and are built for constructing JSON. They accept inputs in the form of JSON objects and arrays, or quotation-wrapped blocks.Any expression, command, or helper used in a data field must be wrapped inside quotation marks.{"to": "/#steps.1.from", "text": "hello {{steps.1.name"}}, "date": "/#fn:dateFormat,steps.1.createdAt"}"/#fn:dateFormat,steps.1.createdAt""{{steps.1.name}}"Note: Commands and helpers wrapped in quotation marks do not automatically resolve to a string output.Escape sequencesSome characters may necessitate the use of escape sequences in order to be processed correctly. Escape sequences are used in workflows to output literal representations of non-printing characters, or special characters that may have alternate meanings in code.A common example, especially when working with data fields, is the use of standard quotation marks inside a string. When a string uses quotation marks to define itself, additional nested quotation marks may cause the string to break. To resolve an issue like this, the offending quotation marks must be escaped with a backslash.{"string": "{{toUpper "one two three"}}"} results in a broken string and an errored workflow step{"string": "{{toUpper \"one two three\"}}"} results in an unbroken string and a successfully processed helperRelated articles:Conditional workflow helpersDate and math workflow helpersString modifying workflow helpersJSON data workflow helpersData validation workflow helpersUnderstand handlebars
  • Conditional workflow helpers

    Conditional workflow helpers let you automate dynamic messaging in Kustomer based on specific criteria or conditions. For example, you can reference a customer's gender correctly if their gender is known, or include special instructions for customers who are part of a VIP program. In this article:If / UnlessElseCondIf CondIs EmptyOrIf / UnlessThe {{#if}} block helper checks to see if the value of an attribute exists, as determined by being truthy, and outputs a string value accordingly. This helper only checks to see if the value exists; it does not verify a specific value.For example, a customer’s country attribute can be checked when writing an automated note and included if it exists.Given steps.1.locations.country = “USA”{{#if steps.1.locations.country}}Customer is from: {{{steps.1.locations.country}}}{{/if}} resolves to the string "Customer is from: USA"Given steps.1.locations.country = null{{#if steps.1.locations.country}}Customer is from: {{{steps.1.locations.country}}}{{/if}} resolves to an empty stringThe {{#unless}} block helper behaves with the opposite functionality, and displays a string of text when the value of an attribute does not exist, as determined by being falsy (for instance, if a customer does not have a country listed).Given steps.1.locations.country = null{{#unless steps.1.locations.country}}No country found{{/unless}}resolves to the string "No country found"While the number value 0 is usually interpreted as falsy, an optional parameter includeZero can be used to interpret the value as truthy instead.{{#if 0}}zero is true{{/if}} resolves to an empty string{{#if 0 includeZero=true}}zero is true{{/if}} resolves to the string "zero is true"{{#unless 0 includeZero=true}}zero is false{{/unless}} resolves to an empty stringA variant /#fn:ifExists function helper is also available to output a string of text when an input is found to have an existing value. Values that are determined to exist by this variant helper deviate from the above definition in that they automatically include the number value 0, as well as the boolean value false.Given steps.1.id = "12345"/#fn:ifExists,steps.1.id,hello world resolves to the string "hello world"Else{{else}} is a dedicated sub-helper block, available for use in conjunction with any block helper syntax. It extends conditional functionality by allowing multiple block helper statements to be chained together. If an initial block helper statement resolves in a null value, an {{else}} block can be inlcuded to attempt additional helper arguments, or to output a default value.{{#if steps.1.locations.country}}{{{steps.1.locations.country}}}{{else if steps.1.locations.region}}{{{steps.1.locations.region}}}{{else}}No country found{{/if}}{{#unless steps.1.locations.region}}No region found{{else unless steps.1.locations.country}}No country found{{else}}{{{steps.1.locations.country}}}{{/unless}}CondThe {{cond}} helper takes if/unless statements a step further by checking an attribute for a specific value and outputting a static string of text. Using conditionals allows for more granularity, allowing for a more dynamic output.Given steps.1.location.country = "USA"{{cond steps.1.location.country USA='United States' CA='Canada' MX='Mexico'}} resolves to the string "United States"Given steps.1.location.country = "CA"{{cond steps.1.location.country USA='United States' CA='Canada' MX='Mexico'}} resolves to the string "Canada"This helper can also be used to check for boolean values true or false.Given steps.1.custom.vip = true{{{cond steps.1.custom.vip true='Customer is VIP' false='Customer is not VIP'}}} resolves to the string "Customer is VIP"You can also implement conditionals in conjunction with multi-level lists. This allows you to create custom messaging based on a dropdown selection. When using this helper to check the value of a multilevel list on a Klass object, IDs of each reviewed value are needed.Note: To find value IDs for a multi-level list, make a GET request to the API endpoint for the appropriate resource Klass - /v1/metadata/:resource - and review data for the multi-level list attribute in question.For example, an organization has a custom "resolutionTree" attribute on the conversation Klass. Level 1 of the list has a 'troubleshooting' option, with 'resolved' and 'bug' featured as nested level 2 options.Given steps.1.custom.resolutionTree = "troubleshooting.bug"{{{cond steps.1.custom.resolutionTree [troubleshooting.resolved]='Issue resolved' [troubleshooting.bug]='Bug report requested'}}} resolves to the string "Bug report requested"A variant /#fn:cond function helper is also available with similar functionality.Given steps.1.location.country = "MX"/#fn:cond,steps.1.location.country,USA=United States,CA=Canada,MX=Mexico resolves to the string "Mexico"If CondThe {{#ifCond}} block helper combines the functionality of the {{#if}} and {{cond}} helpers by outputting a dynamic string, based on a specific attribute value. Attributes queried in this helper can be compared against strings, numbers, booleans, and null.Given steps.1.subject = "Out of office"{{#ifCond steps.1.subject '==' 'Out of office'}}Ignore email{{/ifCond}} resolves to the string "Ignore email"When calling data paths inside the opening and closing blocks, you will need to reference one directory level up.Given steps.1.custom.counterNum = 11{{#ifCond steps.1.custom.counterNum '>=' 10}}The number has reached {{{../steps.1.custom.counterNum}}}{{/ifCond}} resolves to the string "The number has reached 11"Because it is a block helper, {{#ifCond}} has access to the {{else}} sub-helper block, allowing multiple statements to be chained together.{{#ifCond steps.1.custom.countNum '>' 10}}has exceeded 10{{else ifCond ../steps.1.custom.countNum '==' 10}}is 10{{else}}is only {{../steps.1.custom.countNum}}{{/ifCond}}This helper supports the following operators:== (equals)=== (strict equals)!= (not equals)!== (strict not equals)> (greater than)< (less than)>= (greater than or equal to)<= (less than or equal to)&& (both values are truthy)|| (at least one value is truthy)Is Empty{{#isEmpty}} accepts a value and outputs a string if that value is empty. This includes empty strings, arrays, or objects, boolean values, null, and non-existent attributes. Note that the number value 0 is not considered empty.Given steps.1.attributes.data = an empty object{{#isEmpty steps.1.attributes.data}}it's empty!{{/isEmpty}} resolves to the string "it's empty!"Like {{#ifCond}}, data paths used for string interpolation must reference one directory level up.Given steps.1.attributes.data = an empty object{{#isEmpty steps.1.attributes.data}}{{toJSON ../steps.1.attributes.data}}{{/isEmpty}} resolves to the string "{}"Like all block helpers, {{#isEmpty}} has access to the {{else}} sub-helper block, allowing multiple statements to be chained together.{{#isEmpty steps.1.attributes.data.array1}}Array 1 is empty{{else isEmpty ../steps.1.attributes.data.array2}}Array 2 is empty{{else}}Neither array 1 or 2 is empty{{/isEmpty}}For help interpreting arrays and objects as stringified JSON, see JSON Data helpers.OrThe {{or}} helper accepts two values and returns the first truthy value or the last falsy value.Given steps.1.attributes.data = {"val1": "1", "val2": ""}{{or steps.1.attributes.data.val1 steps.1.attributes.data.val2}} resolves to the string "1"{{or steps.1.attributes.data.val2 steps.1.attributes.data.val1}} resolves to the string "1"Related articles:Understand workflow helpersDate and math workflow helpersString modifying workflow helpersJSON data workflow helpersData validation workflow helpersUnderstand handlebars
  • Date and math workflow helpers

    Date and math helpers allow you to build, format, and make calculations, based on dates and numbers, within your workflows.In this article:DateIn Business HoursDate Format (with Moment.js)Date DiffMathFormat CurrencyDateThe {{date}} workflow helper generates a date based on the current time, using the standard date object format of YYYY-MM-DDTHH:MM:SS.SSSZ. This is commonly used for time comparison. For example, conversations configured to send an auto-response might use a custom date attribute to track when an auto-response was last sent.Below are examples of different options for generating dates and how they can be adjusted to fit your needs:{{date 'days' count=0}} resolves to the current day{{date 'days' count=1}} resolves to 1 day ago{{date 'hour' count=-24}} resolves to 24 hours from nowThe following longhand units of time are supported:year or yearsday or dayshour or hoursminute or minutesIn Business HoursThe /#fn:inBusinessHours function helper checks whether a date falls within a team's operational business hours, as defined in Settings  > Administration > Business Schedules. It is commonly used in condition steps to help determine if and when specific actions should be executed.This helper accepts two optional parameters: A date (in standard date-object notation), and a business schedule ID. Given steps.1.createdAt = "2034-01-01T00:00:00.000Z", AND a business schedule ID of "61785fb332a97930e6ab85d2"/#fn:inBusinessHours,steps.1.createdAt,61785fb332a97930e6ab85d2 resolves to the boolean value false ,if Sundays are excluded from the business scheduleIf no date is provided, the helper compares against the current time. If no business schedule ID is provided, the helper will compare against the organization’s default schedule./#fn:inBusinessHours/#fn:inBusinessHours,steps.1.createdAt/#fn:inBusinessHours,61785fb332a97930e6ab85d2Date Format (with Moment.js)Date objects and other recognized date formats can be converted into a desire formats using Moment.js, a library that parses, validates, manipulates, and displays dates. You can customize the output by using any of the formatting parameters listed in their documentation.You can find information on Moment.JS, including a wide variety of notated formatting options, in the following resources:https://momentjs.comhttps://devhints.io/momentThe {{dateFormat}} helper can be used to convert a date into a more user-friendly format. For example, an order date given in standard date-object notation can be converted into a format that is easier to read.Given steps.1.attributes.data.orderDate = "2018-05-04T20:01:51.031Z"{{dateFormat steps.1.attributes.data.orderDate}} resolves to the string "May 4, 2018", leveraging the “LL” format from moment.js as default. The date given to the helper does not need to be in standard date-object notation to be reformatted, so long as it is in a recognized moment.js format. Any unrecognized format will simply result in the output of an empty string.{{dateFormat '05/04/2018'}} resolves to the string "May 4, 2018"An optional format parameter can be included to specify alternate output formats. All moment.js format notations are supported, and can even be strung together to build custom outputs, inserting additional text inside [brackets].{{dateFormat 'May 4, 2018' format='dddd'}} resolves to the string "Friday"{{dateFormat '5.4.18' format='dddd [the] Do [of] MMMM'}} resolves to the string "Friday the 4th of May"{{dateFormat '2018-05-04 20:01' format='YYYY-MM-DD[T]HH:mm:ss.SSS[Z]]'}} resolves to the standard date object "2018-05-04T20:01:00.000Z"Because dates are interpreted in Universal Coordinated Time (UTC), and output in a United States format by default, this helper may not display a date output in your desired timezone or language. To account for this, optional parameters for timezone, inputTimezone, and locale can also be utilized. timezone accepts a timezone abbreviation or region, and adjusts the input date for that timezone, inputTimezone identifies the input date as something other than UTC when making conversions (also by timezone abbreviation or region), and locale allows for outputs in non-English languages or regional conventions.{{dateFormat '2018-05-04 20:01' format='MMMM Do YYYY, h:mma z' timezone='America/New_York' inputTimezone='GMT' locale='en-us'}} resolves to the string "May 4th 2018, 4:01pm EDT"{{dateFormat '2018-05-04 20:01' format='MMMM Do YYYY, h:mma z' timezone='America/New_York' inputTimezone='GMT' locale='es'}} resolves to the string "mayo 4º 2018, 4:01pm EDT"A variant /#fn:dateFormat function helper is also available, which outputs dates in date-object notation by default.Given steps.1.attributes.data.orderDate = "2018-5-4"/#fn:dateFormat,steps.1.attributes.data.orderDate resolves to the date object strong "2018-05-04T00:00:00.000Z"Moment.js notation can be used for date formatting with this variant helper.Given steps.1.attributes.data.orderDate = "05.04.18"/#fn:dateFormat,steps.1.attributes.data.date,MMMM [the] Do, YYYY resolves to the string "May the 4th, 2018"Date DiffThe {{dateDiff}} helper compares two dates (in standard date object notation) and calculates the difference between them. It outputs the result as a string based on the specified unit of time using the format {{dateDiff 'unit_of_time' from=date_1 to=date_2}}.Within this helper, the from parameter is always subtracted from the to parameter. If either parameter is omitted from the statement, that value will default to the current time.{{dateDiff 'years' from='2000-01-01T00:00:00.000Z' to='3000-01-01T00:00:00.000Z'}} resolves to the string "1000"{{dateDiff 'years' from='3000-01-01T00:00:00.000Z' to='2000-01-01T00:00:00.000Z'}} resolves to the string "-1000"{{dateDiff 'days' from=steps.1.lastDone.createdAt}} resolves to the stringified number of full days between the last done time and the current time.This helper only counts fully elapsed units, and does not round up.{{dateDiff 'days' from='2000-01-01T00:00:00.000Z' to='2000-01-01T23:59:59.999Z'}} resolves to the string "0"The following longhand units of time are supported:yearsmonthsweeksdayshoursminutessecondsmillisecondsMathThe {{math}} workflow helper allows basic arithmetic operations to be performed within a workflow step. The result is calculated by accepting two numbers (or their string representations) and an operator as arguments, and output as a stringified numerical value.Given steps.1.custom = {"num9": 9, "num4": 4}{{math steps.1.custom.num9 '+' steps.1.custom.num4}} resolves to the string "13"{{math 9 '-' 4}} resolves to the string "5"{{math 9 '*' '4'}} resolves to the string "36"The following operators are supported:+ (addition)- (subtraction)* (multiplication)/ (division)% (modulo)To convert a stringified number to an literal number value, see the /#fn:parseInt and /#fn:parseFloat functions helpers under JSON Data Helpers. JSON data helpers.Format CurrencyThe {{formatCurrency}} helper takes a literal or stringified number and outputs a string value using standard currency code formatting. An optional currency parameter defaults to "USD", and an optional locale parameter can be used to customize the format according to region.{{formatCurrency 1234.56}} resolves to the string "$1,234.56"{{formatCurrency 1234.56 currency='EUR'}} resolves to the string "€1,234.56"{{formatCurrency '1234.56' currency='EUR' locale='de-DE'}} resolves to the string "1.234,56 €"Numbers with decimal values outside the included range of the specified format will be rounded up or down to that format’s nearest accepted value.Given steps.1.custom = {"number": 1234.56, "currency": "JPY"}{{formatCurrency steps.1.custom.number currency=steps.1.custom.currency}} resolves to the string "¥1,235"This helper will only format the numeric portion of a string up to the first non-numeric character (excluding a decimal point).{{formatCurrency '1,234.56'}} resolves to the string "$1.00"{{formatCurrency '#1234.56'}} resolves to an empty stringRelated articles:Understand workflow helpersConditional workflow helpersString modifying workflow helpersJSON data workflow helpersData validation workflow helpersUnderstand handlebars
  • String modifying workflow helpers

    String modification helpers allow you to adjust the appearance or formatting of a given string. For example, you can use a string helper to standardize customer names by capitalizing the first letter of each word. In the examples shown in this article, the string included after the helper name can be replaced by a standard JSON data path. For example, {{{capitalize 'abc'}}} could be changed to {{{capitalize steps.1.subject}}} to dynamically apply the transformation to a specific data field.Use of these helpers will typically be aided in the use of a triple-stache wrapper (as opposed to a double), though this is not required.In this articleCamel CaseCapitalizeKebab CaseLower CaseLower FirstReplaceSnake CaseSliceSplitStart CaseTo LowerTo UpperTrimUpper CaseUpper FirstCamel Case{{camelCase}} converts a string into camelCase format, where characters in the first word are all non-capitalized, and each word after starts with a capitalized letter. {{{camelCase 'one two three'}}} resolves to the string "oneTwoThree"Capitalize{{capitalize}} converts the first character in a string to its capitalized version, and all remaining characters to non-capitalized versions.{{{capitalize 'one two THREE'}}} resolves to the string "One two three"Kebab Case{{kebabCase}} converts a string into the kebab-case format, where hyphens separate words, and all letters are non-capitalized. {{{kebabCase 'one two three'}}} resolves to the string "one-two-three"Lower Case{{lowerCase}} converts all characters in a string to lower case, with all letters non-capitalized, and words separated on a space.{{{lowerCase 'OneTwoThree'}}} resolves to the string "one two three"Lower First{{lowerFirst}} converts the first character in a string to its capitalized version.{{{lowerFirst 'ONE TWO THREE'}}} resolves to the string "oNE TWO THREE"Replace{{replace}} finds matches for a search pattern and replaces them with a new value. The search pattern may be a string or use RegEx.{{{replace 'one two five' search='five' newvalue='three'}}} resolves to the string "one two three"{{{replace 'five five five' search='five' newvalue='three'}}} resolves to the string "three three three"{{{replace '1ne tw2 three' search='1|2' flags='g' newvalue='o'}}} resolves to the string "one two three"SliceThe /#fn:slice function helper takes a string input and returns a sliced version of that string, based on two specified indices. If the first index is not provided, it defaults to zero. If the second index is not provided, it defaults to the end of the string.Given steps.1.name = "Bruce"/#fn:slice,steps.1.name,1,4 resolves to the string "ruc"/#fn:slice,steps.1.name,2 resolves to the string "uce"/#fn:slice,steps.1.name,,2 resolves to the string "Br"Snake Case{{snakeCase}} converts a string into snake_case format, where separated words are connected by an underscore, and all letters are non-capitalized. {{{snakeCase 'one two three'}}} resolves to the string "one_two_three"Split{{split}} breaks a string into an array of strings at a defined separator and returns one string at a defined index. This helper will not return a full array array.{{{split 'one-two-three' separator='-' index=1}}} resolves to the string "two"Start Case{{startCase}} converts a string into Start Case format, where the first letter of each word is capitalized, all remaining letters are non-capitalized, and words are separated by spaces.{{{startCase 'one two THREE'}}} resolves to the string "One Two Three"To Lower{{toLower}} converts all characters in a string into non-capitalized versions.{{{toLower 'ONE TWO THREE'}}} resolves to the string "one two three"To Upper{{toUpper}} converts all characters in a string to their capitalized version.{{{toUpper 'one two three'}}} resolves to the string "ONE TWO THREE"Trim{{trim}} removes leading and trailing whitespace in the string. You can also use the trimStart and trimEnd variation helpers.{{{trim '   one two three   '}}} resolves to the string "one two three"{{{trimStart '   one two three   '}}} resolves to the string "one two three   "{{{trimEnd '   one two three   '}}} resolves to the string "   one two three"Upper Case{{upperCase}} converts all characters in a string to UPPER CASE, with all letters capitalized, and words separated on a space.{{{upperCase 'OneTwoThree'}}} resolves to the string "ONE TWO THREE"Upper First{{upperFirst}} converts the first character in a string to its capitalized version.{{{upperFirst 'one two THREE'}}} resolves to the string "One two THREE"Related articles:Understand workflow helpersConditional workflow helpersDate and math workflow helpersJSON data workflow helpersData validation workflow helpersUnderstand handlebars
  • Data validation workflow helpers

    Data validation helpers are designed to generate, verify, and reformat data for the purposes of utilizing it in an expected format.In this article:Random IDEmail Address ValidationPhone Number ValidationEscapeEscape RegExpMarkdown to HTMLRemove MarkdownURI EncodingBase64 EncodingAuth HMACGet App SettingRandom ID{{randomId}} generates a string of random alphanumeric characters. For example, you can use it to create a more user-friendly conversation tracking number to share with customers instead of the longer, auto-generated conversation ID. The length of the string generated by this helper is set to 10 characters by default, but a different length can be specified using the optional size parameter if needed.{{{randomId}}} will result in a randomly generated string like "KGGCJG3FGP"{{{randomId size=6}}} will result in a randomly generated string like "6O9L4M"Email Address ValidationThe /#fn:isValidEmailAddress function helper checks whether a string contains the @ character with at least one character on either side, using the regex "/.+@.+/". It returns a boolean value of either true or false. This is useful for checking if a string may or may not be a valid email address, though there are scenarios in which a value of true may be returned for an invalid email address.Given steps.1.attributes.data.email = "www.kustomer.com"/#fn:isValidEmailAddress,steps.1.attributes.data.email resolves to the boolean value falseGiven steps.1.attributes.data.email = "k@t"/#fn:isValidEmailAddress,steps.1.attributes.data.email resolves to the boolean value truePhone Number ValidationThe /#fn:isValidPhoneNumber function helper checks if a string resolves to a valid phone number format, returning either a boolean value of true or false. It accepts numbers of various formats (for example, +1 (555) 123-4567 or 1234567), though numbers from outside the US and Canada must include a country code (e.g. "+44 7911 123456").This helper uses the phoneutl.parse method from the Google's "libphonenumber" library to validate phone number values.Given steps.1.attributes.data.phone = "73255"./#fn:isValidPhoneNumber,steps.1.attributes.data.phone resolves to the boolean value falseEscape{{escape}} detects HTML special characters &, <, >, ', and ", and converts them to their corresponding HTML entities, even inside a triple-stache expression.{{{escape 'Zak & Sara'}}} resolves to the string "Zak &amp; Sara"Escape RegExp{{escapeRexExp}} adds escape sequences to help display literal representations of special characters that may have alternate meanings in code, such as ^, $, ., *, +, ?, (, ), [, ], {, }, and |.{{{escapeRegExp '(https://kustomer.com/)'}}} resolves to the string "\\(https://kustomer\\.com/\\)"Note: Additional escape sequence characters are included to properly escape an escape sequence when passed on.Markdown to HTMLThe {{markdownToHTML}} helper converts text formatted in Markdown (a popular markup language) into equivalent HTML syntax, including escape sequencing for necessary characters.Given steps.1.custom.markdownStr = "**[Kustomer](https://www.kustomer.com)**"{{markdownToHTML steps.1.custom.markdownStr}} resolves to the string "<strong><a href=\"https://www.kustomer.com\">Kustomer</a></strong>"Remove MarkdownThe {{removeMarkdown}} helper removes Markdown syntax and formatting, resulting in a plain text string.Given steps.1.custom.markdownStr = "**[Kustomer](https://www.kustomer.com)**"{{removeMarkdown steps.1.custom.markdownStr}} resolves to the string "Kustomer"URI EncodingThe {{uriEncode}} helper converts a string into an encoded format suitable for internet transmission, while {{uriDecode}} does the reverse.Given steps.1.attributes.data.string = "Kustomer 2: Electric Boogaloo"{{uriEncode steps.1.attributes.data.string}} resolves to the encoded string "Kustomer%202%3A%20Electric%20Boogaloo"{{uriDecode Kustomer%202%3A%20Electric%20Boogaloo}} resolves to the decoded string "Kustomer 2: Electric Boogaloo"URI encoding and decoding is also available with variant function helpers /#fn:URIEncode and /#fn:URIDecode.Given steps.1.attributes.data.string =  "Kustomer%202%3A%20Electric%20Boogaloo"/#fn:URIDecode,steps.1.attributes.data.string resolves to the decoded string "Kustomer 2: Electric Boogaloo"Base64 EncodingThe {{#base64Encode}} block helper converts a string of text into Base64-encoded binary data, while {{#base64Decode}} does the reverse. An optional uriEncode parameter accepts boolean values (with a default value of false) and can be used to apply URI encoding to any output string.Given steps.1.attributes.data.string = "Kustomer 2: Electric Boogaloo"{{#base64Encode}}{{steps.1.attributes.data.string}}{{/base64Encode}} resolves to the encoded string "S3VzdG9tZXIgMjogRWxlY3RyaWMgQm9vZ2Fsb28="{{#base64Decode uriEncode='true'}}S3VzdG9tZXIgMjogRWxlY3RyaWMgQm9vZ2Fsb28={{/base64Decode}} resolves to the decoded string "Kustomer%202%3A%20Electric%20Boogaloo"Note: Due to the way in which these block helpers accept an input, {{else}} blocks will have no discernible effect.Auth HMACThe {{authHMAC}} helper generates a hash-based message authentication code (HMAC) from a string, using a hash function and secret key for verification. It accepts optional string parameters for secretKey, algorithm, and encoding. The algorithm parameter supports all standard cryptographic hash function configurations for HMAC, while the encoding parameter supports all standard key encoding methods.{{{authHMAC steps.1.custom.password secretKey='12345' algorithm='sha256' encoding='base64'}}}The algorithm parameter supports all standard cryptographic hash function configurations for HMAC, while the encoding parameter supports all standard key encoding methods.Get App Setting/#fn:getAppSetting is a function helper designed to review an installed app in your org and return the stored value for a specified setting field. For example, it might be used to access the values stored in the API Key, Kustomer URL, and Seconds until send settings fields found within the installed Stella Connect app.When using this helper, up to three parameters may be utilized, noted as "key", "default value", and "default value type". Whichever parameter is used last must end using the # symbol.The "key" identifies the app and specific settings field. If only the "key" is provided, the helper will return the stored value as a string.Stored settings values can be queried and returned using the "key" parameter, which must specify the app and nested field names (this information can be obtained by sending a GET request to the /v1/apps API endpoint and reviewing data for the app in question).Assume the following Stella Connect app settings: apiKey = "12345", kustomerBaseURL = "https://companycorp.kustomerapp.com", secondsUntilSend = 86400/#fn:getAppSetting,stella_connect_kustomer.default.kustomerBaseURL# resolves to the string "https://companycorp.kustomerapp.com"/#fn:getAppSetting,stella_connect_kustomer.default.secondsUntilSend# resolves to the number value 86400A variant {{{ setting }}} handlebars helper may also be used to similar effect. This variant utilizes the same three parameters (without the need for the # symbol), but because it is a handlebars helper, it will only ever output a string value.{{{ setting stella_connect_kustomer.default.secondsUntilSend }}} resolves to the string ”86400”Note: The {{{ setting }}} helper is unusual, in that it requires three handlebars wrappers, and separated spacing.When attempting to use either variant to access the settings of a privately installed or custom app, the org number in which the app is installed may need to be included in the app name./#fn:getAppSetting,mycustomapp_5e163d54a1995b0023788621.default.authToken#{{{ setting mycustomapp_5e163d54a1995b0023788621.default.authToken }}}App settings that are marked as containing a secret will return masked strings./#fn:getAppSetting,stella_connect_kustomer.default.apiKey# resolves to the string "****"{{{ setting stella_connect_kustomer.default.apiKey }}} resolves to the string "****"Masked values can still be incorporated into further actions when needed. For example, a masked value containing an authorization token can be passed directly into the headers of an API call.{"headers": {"Authorization": "/#fn:getAppSetting,stella_connect_kustomer.default.apiKey#"}}{"headers": {"Authorization": "{{{ setting stella_connect_kustomer.default.apiKey }}}"}}Should the "key" ever fail to be recognized as a valid app or app setting, or if no value is found within an identified setting, a value of null will be returned, resulting in an empty object or string. In these scenarios, the "default value" parameter is designed to output a backup value./#fn:getAppSetting,stella_connect_kustomer.default.password# resolves to an empty object/#fn:getAppSetting,stella_connect_kustomer.default.password,1234# resolves to the string "1234"{{{ setting stella_connect_kustomer.default.password 1234 }}} resolves to the string "1234"The "default value type" parameter indicates the intended data-type of the "default value" output, allowing the helper to attempt to return the value properly. This parameter defaults to a string value, and makes no significant impact when used in conjunction with the handlebars helper variant./#fn:getAppSetting,stella_connect_kustomer.default.password,1234,number# resolves to the number value 1234{{{ setting stella_connect_kustomer.default.password 1234 number }}} resolves to the string "1234"The following longhand value data-types are supported:stringnumberbooleanRelated articles:Understand workflow helpersConditional workflow helpersDate and math workflow helpersString modifying workflow helpersJSON data workflow helpersUnderstand handlebars
  • JSON data workflow helpers

    JSON data helpers allow you to manipulate, format, and extract information from the JSON data generated or received within workflows.In this article:EachWithLookupTo JSONParse JSONParse Int / Parse FloatParse BoolTransformMapIncluded Resource AttributeEachThe {{#each}} block helper iterates through an array or object and concatenates each found value into a string.Given steps.1.attributes.data.letters = ["a", "b", "c"] OR {"firstLetter": "a", "secondLetter": "b", "thirdLetter": "c"}{{#each steps.1.attributes.data.letters}}test{{/each}} resolves to the string "testtesttest"The value at each index or key can be accessed using the this instance variable.Given steps.1.attributes.data.letters = ["a", "b", "c"] OR {"firstLetter": "a", "secondLetter": "b", "thirdLetter": "c"}{{#each steps.1.attributes.data.letters}}{{this}}, {{/each}} resolves to the string "a, b, c, "Data path notation can access nested attribute values when working with sequentially nested objects.Given steps.1.attributes.data.letters = [{"letter": "a"}, {"letter": "b"}, {"letter": "c"}] OR {"firstLetter": {"letter": "a"}, "secondLetter": {"letter": "b"}, "thirdLetter": {"letter": "c"}}{{#each steps.1.attributes.data.letters}}{{this.letter}}, {{/each}} resolves to the string "a, b, c, "The trailing comma and whitespace in the above examples may be undesirable in certain scenarios. Fortunately, @first and @last helper variables can be used in conjunction with conditional helpers such as {{#if}} to define behavior on the first or last iteration respectively, allowing a character like a comma to be omitted from the final loop. Learn moreGiven steps.1.attributes.data.letters = ["a", "b", "c"] OR {"firstLetter": "a", "secondLetter": "b", "thirdLetter": "c"}{{#each steps.1.attributes.data}}{{this}}{{#if @last}}{{else}}, {{/if}}{{/each}} resolves to the string "a, b, c"Additional @index and @key helper variables are also available to represent the current loop iteration number and object attribute name, respectively. Given steps.1.attributes.data = {"firstLetter": "a", "secondLetter": "b", "thirdLetter": "c"}{{#each steps.1.attributes.data}}{{@index}}-{{@key}}: {{this}}{{#if @last}}{{else}}, {{/if}}{{/each}} resolves to the string "0-firstLetter: a, 1-secondLetter: b, 2-thirdLetter: c"Note: Nested {{#each}} blocks can access iteration variables via depth-based paths. For example, @../index can be used to access and reference the parent index.As a block helper, {{#each}} has access to the {{else}} sub-helper, allowing multiple statements to be chained together, should the initially targeted array or object be empty or not exist.{{#each steps.1.attributes.data.array1}}{{this}}{{else each steps.1.attributes.data.array2}}{{this}}{{else}}No items found{{/each}}To parse and fully convert stringified JSON into literal JSON, use the /#fn:parseJSON function helper. This will require an additional workflow step, such as "Transform Generic."WithThe {{#with}} block helper accepts an object or an array as an argument, and allows contained values to be locally referenced by key or index.Given steps.1.attributes.data.hero = {firstName": "Peter", "lastName": "Parker"}{{#with steps.1.attributes.data.hero}}My name is {{firstName}} {{lastName}}{{/with}} resolves to the string "My name is Peter Parker"Given steps.1.attributes.data.hero = ["Peter", "Parker"]{{#with steps.1.attributes.data.hero}}My name is {{0}} {{1}}{{/with}} resolves to the string "My name is Peter Parker"As a block helper, {{#with}} has access to the {{else}} block, allowing multiple statements to be chained together, should the initial statement resolves to a null value.{{#with steps.1.attributes.data.hero1}}{{firstName}} {{lastName}}{{else with steps.1.attributes.data.hero2}}{{firstName}} {{lastName}}{{else}}No heroes found{{/with}}LookupThe {{lookup}} helper retrieves the value of an attribute using its key name, making it useful for dynamically referencing object data. It accepts two parameters: an object, and a key that specifies the desired data within the object.Given steps.1.attributes.data = {firstName": "Peter", "lastName": "Parker"}{{lookup steps.1.attributes.data 'firstName'}} resolves to the string "Peter"Like all helper expressions, the lookup helper only outputs a string. If the value of the identified attribute is an array, its items will be concatenated into a single string, without array brackets. If the value is an object, it will be represented as the string "[object Object]".To interpret arrays and objects as stringified JSON data, use the toJSON helper.To JSONThe {{toJSON}} helper converts an object into a stringified JSON format, including escaped characters. This is useful when array data is missing standard brackets or when object data defaults to the string "[object Object]".Given steps.1.attributes.data = {"hero": {firstName": "Peter", "lastName": "Parker"}, "team": ["Spiderman", "Daredevil"], {"identifier": "hero"}{{toJSON steps.1.attributes.data.team}} resolves to the stringified JSON "[\"Spiderman\",\"Daredevil\"]"{{toJSON (lookup steps.1.attributes.data steps.1.attributes.data.identifier)}} resolves to the stringified JSON "{\"firstName\":\"Peter\",\"lastName\":\"Parker\"}"To parse and reference a specific value within stringified JSON, see the parseJSON helper.To parse and fully convert stringified JSON into literal JSON, see /#fn:parseJSON. Making this conversion sequentially will require an additional workflow step, such as "Transform Generic."Parse JSONThe /#fn:parseJSON function helper accepts stringified representations of JSON data and converts to an output of literal JSON data.Given steps.1.attributes.data.stringifiedJSON = "{\"firstName\":\"Peter\",\"lastName\":\"Parker\"}"/#fn:parseJSON,steps.1.attributes.data.stringifiedJSON resolves to the object {"firstName": "Peter", "lastName": "Parker"}To capture an output of stringified JSON data, see the {{toJSON}} helper.The {{#parseJSON}} block helper similarly accepts stringified JSON data. However, this helper's functionality is more aligned with the {{#with}} helper, as it will only extract specific values by key or index.Given steps.1.attributes.data.stringifiedHero = "{\"firstName\":\"Peter\",\"lastName\":\"Parker\"}"{{#parseJSON steps.1.attributes.data.stringifiedHero}}My name is {{firstName}} {{lastName}}{{/parseJSON}} resolves to the string "My name is Peter Parker"Given steps.1.attributes.data.stringifiedHero = "[\"Peter\",\"Parker\"]"{{#parseJSON steps.1.attributes.data.stringifiedHero}}My name is {{0}} {{1}}{{/parseJSON}} resolves to the string "My name is Peter Parker"Parse Int / Parse FloatThe /#fn:parseInt function helper converts a stringified number value into a standard number-type integer value, while /#fn:parseFloat converts a stringified number value into a number-type value with any included decimals (also known as a "float").Any string that begins with a non-numeric character will result in a number value of 0. Any stringified number with additional non-numeric characters will result in the number up to the first non-numeric characterGiven steps.1.attributes.data.number = "10"/#fn:parseInt,steps.1.attributes.data.number resolves to the number value 10Given steps.1.attributes.data.number = "10.90"/#fn:parseFloat,steps.1.attributes.data.number resolves to the number value 10.9/#fn:parseInt,steps.1.attributes.data.number resolves to the number value 10Given steps.1.attributes.data.number = "10abc"/#fn:parseFloat,steps.1.attributes.data.number resolves to the number value 10Given steps.1.attributes.data.number = "abc10"/#fn:parseInt,steps.1.attributes.data.number resolves to the number value 0Parse BoolThe /#fn:parseBool helper converts a stringified boolean value (true or false) into a standard boolean value. Any unrecognized input will default to false.Given steps.1.attributes.data.open = "true"/#fn:parseBool,steps.1.attributes.data.open resolves to the boolean value trueTransformThe /#fn:transform helper performs bulk updates to the names of object keys in an array of objects and returns the full array with the updated keys.Given steps.1.message = [{"subject": "message a", "preview": "hello"}, {"subject": "message b", "preview": "goodbye"}]/#fn:transform,steps.1.messages,title=subject,body=preview resolves to the array [{"title": "message a", "body": "hello"}, {"title": "message b", "body": "goodbye"}]Map Given an array of sequential objects, the /#fn:map function helper assembles the values of a specified recurring object key and outputs them into a unique array. For example, an agent can use this helper to take an array of customer objects and create a new array containing just the listed email addresses.Given steps.1.attributes.data = {"customers": [{"name": "Agent A", "email": "email-a@example.com"}, {"name": "Agent B", "email": "email-b@example.com"}]}/#fn:map,steps.1.attributes.data.customers,email resolves to the array ["email-a@example.com", "email-b@example.com"]In addition to arrays, this helper can be used on sequential objects with a repeated key attribute.Given steps.1.attributes.data = {"firstAgent": {"name": "Agent A", "email": "email-a@example.com"},  "secondAgent": {"name": "Agent B", "email": "email-b@example.com"}}/#fn:map,steps.1.attributes.data,email resolves to the array ["email-a@example.com", "email-b@example.com"]For sequential array values, the desired index can target the desired values from the array.Given steps.1.attributes.data = {"firstAgent": ["Agent A", "email-a@example.com"], "secondAgent": ["Agent B", "email-b@example.com"]}/#fn:map,steps.1.attributes.data,1 resolves to the array ["email-a@example.com", "email-b@example.com"]If a specific target is not defined, the entire array will be returned in full. Additionally, strings can be mapped to return an array of individual characters.Given steps.1.name = "Bruce"/#fn:map,steps.1.name resolves to the array ["B", "r", "u", "c", "e"]Included Resource AttributeThe /#fn:findIncludedResourceAttribute function helper takes an array of objects as an argument, and targets one if the objects from which to return a specified attribute value. The targeted object is identified as the first object that contains a match for a set of provided attribute values.For example, in an array of message objects, this helper could return the channel used for a message containing a specified subject line, or it could return the subject line for a message by a specified direction and channel.Given steps.1.messages = [{"subject": "message a", "direction": "in", "channel": "email"}, {"subject": "message b", "direction": "out", "channel": "email"}, {"subject": "message c", "direction": "in", "channel": "sms"}]/#fn:findIncludedResourceAttribute,steps.1.messages,subject=message a,channel resolves to the string "email"/#fn:findIncludedResourceAttribute,steps.1.messages,direction=in,channel=sms,subject resolves to the string "message c"When matching a value to target an object, only string-type values can used for matching, although selecting nested child attributes via data path is supported. The output will always be the data type of the queried attribute.Given steps.1.attributes.data = [{"operations": {"start": "combine", "end": "reduce"}, "numbers": [1, 3, 5]}]/#fn:findIncludedResourceAttribute,steps.1.attributes.data,operations.start=combine,numbers resolves to the array [1, 3, 5]Related articles:Understand workflow helpersConditional workflow helpersDate and math workflow helpersString modifying helpersData validation workflow helpersUnderstand handlebars
  • Understand handlebars

    Handlebars is a templating language used to retrieve and display dynamic content. Its syntax consists of a set of {{double}} or {{{triple}}} curly braces wrapped around a block of data or dedicated handlebars helper. Statements made with handlebars may also be referred to as "handlebars expressions" or "handlebars blocks".Handlebars are utilized as code, and are designed to output a string of text when called, commonly using a data path to do so. Handlebars may also use helpers to manipulate data, which have a great deal of utility in Kustomer workflows.See Handlebars’ official documentation at https://handlebarsjs.com/guide to learn more.In this article:String interpolation & data pathsFormatting handlebarsNesting handlebars helpersString interpolation & data pathsHandlebars allow for basic string interpolation of object attribute values. In workflow steps, an attribute value will commonly be referenced with workflow initiation command syntax, followed by the attribute's JSON data path (/#steps.STEP_ID.ATTRIBUTE_NAME). However, the same value can also be referenced by wrapping the data path inside a handlebars expression ({{steps.STEP_ID.ATTRIBUTE_NAME}}). This allows the attribute value to be interpolated within the context of a larger string.As one example, you may wish to greet customers by name when using a workflow to send automated messages.In this example, the body input field of a Send Message step is filled with the text Hi {{steps.GEKp2Gib.firstName}}! The data path inside the handlebars dynamically retrieves and displays the first name of the customer found in the previous action step. If the customer's name is Mindy Sinclair, the output text will read "Hi Mindy!".To better understand this process, and JSON data paths, the example can be broken down further into three parts:steps access the array of steps containing all previous output data generated by the running workflowGEKp2Gib is the step ID of a specific previous step, contained within the steps arrayfirstName is the attribute name for the value "Mindy", found in the GEKp2Gib step JSON data paths may be longer when attributes contain nested child data. For example, data received via webhook will usually be accessible within a data object nested inside an attributes object (steps.1.attributes.data).Formatting handlebarsWhen using a handlebars expression to interpolate or reference a string value, you can use double or triple curly braces (sometimes called a "triple-stache").Characters returned from double handlebars will be HTML-escaped, while characters returned from a triple-stache will be considered "raw", with no change in appearance.Given steps.1.name = "Zak & Sara"{{steps.1.name}} resolves to the URL encoded string "Zak &amp; Sara"{{{steps.1.name}}} resolves to the non-encoded string "Zak & Sara"Because handlebars expressions are only capable of outputting a string value, they will always attempt to convert non-strings values into strings, with varying degrees of success.Given steps.1.attributes.data = {"string": "2", "number": 2, "boolean": true, "array": ["a", "b", 3], "object": {"nestedString": "2"}, "null": null}{{steps.1.attributes.data.string}} resolves to the string "2"{{steps.1.attributes.data.number}} resolves to the string "2"{{steps.1.attributes.data.boolean}} resolves to the string "true"{{steps.1.attributes.data.array}} resolves to the string "a,b,3"{{steps.1.attributes.data.object}} resolves to the string "[object Object]", which can be handled with additional helpers{{steps.1.attributes.data.null}} resolves to an empty stringNesting handlebars helpersExpression helpers can be used as arguments inside other expression helpers through the use of subexpressions, which are enclosed in a set of parentheses. For example, {{helper (subexpression)}}As an example, you may need to look up complex JSON data using the {{lookup}} and {{toJSON}} helpers:{{{toJSON (lookup steps.1.attributes 'data')}}}Or, you might choose to format a string with multiple string helpers:{{{toLower (snakeCase steps.1.name)}}}You may even wish to use multiple levels of subexpressions. For example, you might nest a {{date}} helper inside a {{dateDiff}} helper, which is then nested inside a {{math}} helper.{{{math (dateDiff 'days' to=(date 'days' count=-1)) '/' 2}}}Both expression and block helpers can be nested between a block helper's opening and closing blocks as a sub-helper. For example, the {{formatCurrency}} expression helper can be placed inside {{#ifCond}} to determine how a number needs to be formatted.{{#ifCond steps.1.custom.currencyCode '!=' 'USD'}}{{formatCurrency 100 currency=../steps.1.custom.currencyCode}}{{else}}{{formatCurrency 100}}{{/ifCond}} Similarly, an {{#if}} block helper can be placed inside {{#each}} to determine which string to output in a loop.{{#each steps.1.attributes.data.array}}{{#if  this}}{{this}}{{else}}N/A{{/if}}{{/each}} Related articles:Understand workflow helpersConditional workflow helpersDate and math workflow helpersString modifying workflow helpersJSON data workflow helpersData validation workflow helpers
Powered by Kustomer