User's GuideAdvanced FeaturesiPost Template Language

iPost Template Language

iPost Template Language (iTL) is a proprietary programming language that allows for personalization, dynamic content, conditional formatting and scripting in iPost Emails.

In addition to the low-level iTL language discussed in this document, iTL provides a Server-Side Javascript (SSJS) component that may be used to create dynamic documents in a more broadly familiar language. Certain operations such as conditionally including or excluding large sections of HTML (or text) are not easily managed with SSJS blocks, so direct use of iTL is sometimes still required. The iPost Enterprise UI provides tools for building snippets of content and for composing dynamic content from those snippets, so often it is enough to understand how to use iTL Dynamic Variables (see below) when composing your Email content.

Why iTL

iTL was developed to enable customers to embed message personalization and customization markup in their documents, rather than write programs that emit the document text. This markup has to work just as well in plain text documents as it does in HTML, yet do so without interfering with any markup that is intended to appear in the message as delivered to its final recipient. XML was considered, but ultimately rejected because it adds a large amount of extra syntax to each document and its structure is confusingly similar to HTML.

At the same time, in order to generate a large volume of email messages at very high speed, it was necessary to at least partially "compile" the documents and to prefetch the database rows that would participate in the final message assembly. To address all these requirements, iTL provides a regularly structured language that can be unambiguously interleaved with HTML.

How Does it Work?

The body of an email message is composed from the user supplied email content and a variety of data sources.  This conversion happens in two steps.

  1. The first step is when content is added or created in an Email within iPost.  It is then analyzed and validated when Previewing the content.
  2. The second step occurs when the recipient of the message has been identified, so that the final presentation can be personalized on an individual basis.

In general, in computing the final presentation, the content is copied verbatim, except when an iTL element is encountered. iTL elements disappear from the completed content, replaced by the text (including HTML markup, etc.) that the dynamic elements have calculated. This is discussed in more detail under iTL and Documents below.

Terminology

The following terms are used throughout this document:

Term Definition
Contact
A potential recipient of an email message. Any recipient located in list(s) or data table(s) in your account.
Audience The list(s) or data table(s) containing the contacts that become recipients of the email message.
Contact Data
Demographic data found in database fields that are known about each contact. This includes API payload fields and data fields found in sendable data tables in the Audience, but does not include fields from other data tables. This is also referred to as contact_info.
Document
Email Content added to or created in an Email in your account that may or may not contain iTL dynamic variables or macros.
Activation
The first processing step in converting email content to its final presentation form. This step, which occurs during validation when moving to the Preview of the email content, checks the document syntax for errors and performs some pre-processing to speed up the final conversion.
Dynamic Variable
An iTL string used to insert Contact Data fields into the email content.
Macro
A string of iTL logic found in a document that is replaced during activation with new (computed) content. 
Blob
An encrypted string of letters and numbers that identifies the recipient of an email message, the send ("mailing") from which the message originated, and in some cases a specific URL from the original mailing content. Used for recording recipient engagement with the message.
Mailing
The email messages sent to the audience configured in the email activity of the automation.
Opt-out
To unsubscribe from an email list; to request that no further messages be sent to a particular email address. An "opt-out URL" is the web address, usually of an HTML form and often of a hosted form, where the recipient can choose to opt-out.

Quick Start Guide

Common operations are shown here. See below for more details and advanced examples.

Desired Action iTL Example
Insert value of field_name from Contact Data
{\var:field_name}
Insert content only when field has a value

{\if {\var:field_name}

 {content when field has a value}

}

Insert field1 if not empty, else field2
{\or {\var:field1} {\var:field2} }
Insert content if either field has a value

{\if {\or {\var:field1} {\var:field2} }

 {content when either has a value}

}

Insert field2 if field1 is not empty

{\and {\var:field1} {\var:field2} }


Insert content when both fields have a value

{\if {\and {\var:field1} {\var:field2} }

 {content when both have a value}

}

Search for a string in a field**
{\match {\var:field_name} \"string\"}
Change content based on a field value

{\if {\match {\var:field_name} \"string\"}
 {content when string appears}

 {content when string does not appear}
}

Invert a test (using search** as example)
{\not {\match {\var:field_name} \"string\"} }
Test whether content is HTML or plain text
{\htmlp} or {\textp}
Insert the recipient's email address
{\recipient_addr}
Insert the Nth Email Tracking Parameters
{\emailparam:N}
Link to your iPost-hosted preferences form*
<a href={\opt_out_link}>...</a>
Link to View In Browser for this message*
<a href={\viewmessage_link}>...</a>
Test for View In Browser display
{\viewmessagep}

These links are present in the default header and footer available for every Email content, so you aren't required to create them yourself. Omit the HTML markup if you are using these macros in plain text content.

** The \match operator is case-sensitive by default, see below.

iTL and Documents

The most important purpose of iTL is to tailor your Email content for each recipient and each experience you want to present. That means everything from simple insertion of names and demographic data, to creating entirely unique combinations of images and text in each message. For example, a typical use case for iTL conditional operators is to use them for populating product information in Browse and/or Cart Abandon emails. The email can be created to populate one to many products depending on the data including in the Browse/Cart Abandon data sent to a journey.

To facilitate this, iTL is designed so that other content can freely flow around it, but also freely flow within it. The content of your email that appears outside a macro is left unchanged (except for automatic URL tracking). Inside a macro, iTL preserves words and whitespace to make it easy to enclose sections of content for conditional selection. iTL syntax is designed to minimize possible misinterpretation of common HTML and plain-text constructions, so with a few exceptions, you can focus on prose and design and not be concerned about protecting yourself from the markup language.

When the fully formed document is converted into a final email message, each iTL macro is replaced in the completed content by the text of its value. Sometimes that is an empty string and the iTL entirely disappears. More often the value is the result of a dynamic variable replacement. It may also be one of the branches of a conditional construct, or may be content drawn from a database as in the Cart Abandonment example. The rest of the content flows around this, creating a custom presentation.

Syntax

An expression in iTL can be any of:

  • An ordinary text string, excluding whitespace
  • An identifier reference, which is a word introduced by a backslash: \identifier
  • A list of other expressions, enclosed in curly braces: {some words here}
  • A string literal enclosed in escaped quotation marks: \"literal words\"

A Dynamic Variable or macro in your Email content is a special format of iTL expression designed to be easily distinguished from other text and markup. A Dynamic Variable or macro is always introduced with the 2-character sequence {\ and ends with a matching }. Other { and } characters must occur in balanced pairs inside such a macro. If for some reason an un-paired "{" or "}" is needed inside the expression, it must be contained inside a string literal or preceded by a backslash: \{ or \}.

More details can be found in the discussion of macros, below.

Placing { and } (without spaces) around an identifier reference has two possible meanings:

  1. If the identifier refers to a function, it creates a subroutine call using that identifier as the function name.  This is not the same as referencing the value of the identifier.  This is explained in the next section.
  2. Otherwise, it creates a list containing the value of the identifier.

Unless you are using a macro replacement in email text, avoid putting braces around identifiers when you do not expect one of those two effects.  See also iTL for Subroutines for ways to create your own callable functions.

Subroutine

A subroutine or function call occurs any time the first identifier in a list is the name of an operation. iTL thus uses prefix notation, placing the name of an operation before its operands. Experienced programmers will notice a similarity to the Scheme programming language.

Example:  

{\max 7 6 9 4}
  • \max is an operation that returns its numerically largest argument
  • the value of this expression therefore is 9

You can create your own new subroutines.  See iTL for Subroutines below.

Nesting and Order of Operations

When an expression (including a macro) is evaluated, it produces a value, which can then be embedded into other expressions. Arguments are evaluated in order: leftmost innermost.

Example:  

{\max {\add 3 4} {\add 1 5} }
  • {\add 3 4} and {\add 1 5} are the two arguments for \max
  • {\add 3 4} is the leftmost innermost argument and gets evaluated first.
  • {\add 3 4} is an expression itself and when evaluated, it returns 7
  • {\add 1 5} is the second argument for \max and evaluates as 6
  • The outer expression becomes: {\max 7 6 } and returns 7

Dynamic Variables

The format for a Dynamic Variable is: {\var:FIELD_NAME} where FIELD_NAME is replaced by the name of the Contact Data field that contains the desired value.

Example: 

Dear {\var:first_name},

Note that Dynamic Variables are replaced by an empty string in all these cases:

  • The database value of the field is NULL
  • The value of the field is empty string
  • The named field does not exist in the Contact Data

Dynamic Variables also allow for a default value to be added to the iTL to be used in cases where no value is present for a contact. You can specify alternative, default content to be displayed in its place, by adding a string after the field name:

Example: 

Dear {\var:first_name Customer},

If you want to use strings that contain spaces in the iTL variable, you will need to wrap them with escaped double quotes: \".

Example: 

Dear {\var:first_name \"Valued Customer\" } ,

Please see Personalization for more information on dynamic variables and other standalone iTL strings.

Encoding/Decoding

The optional \decode and \encode flags control the conversion of characters such as "<" and ">" from or into encoded values for proper HTML display. To remove any existing HTML encoding in a field value, add \decode=yes after the field name in your dynamic variable. The default for decoding is "no".  If the value of the field already includes HTML formatting, use \encode=no to avoid double-encoding. The default for encoding is "yes", which implies that field values should be protected from HTML interpretation. Both options may be used to convert a field to HTML and then output it literally. Use caution with these options on values that represent URLs.

Updating Dynamic Variables

To change the value of a Dynamic Variable, or to add a new Dynamic Variable, only for personalization of a the current message, use: {\set_var \name=FIELD_NAME VALUE}

Macros

Macros consist of various iTL elements used together to dynamically render content within an email message. The format for macros follows the syntax referenced above, using prefix notation, placing the name of each operation first in each macro. When a macro is evaluated, its final result is the value of the last iTL expression contained in the macro. In many cases a macro is a single expression, so the result is simply the return value of the macro. This result is converted into a text string and replaces the macro in the personalized Email content.

Comments

Comments can be inserted into iTL strings using \;. The comment extends to the end of the line and must be entirely inside a pair of braces, so the final brace of the macro cannot be on the same line as the start of the comment.

 Example:

{\add 3 1 4  \; comments here
}

Lists and Grouping

An iTL macro is always distinguished from the surrounding content by the introductory {\ and concluding }. However, within a macro, iTL uses balanced braces to form lists of elements. For example, you can make simple lists of words: {fly spider bird cat dog goat cow horse}. Such a list is an expression whose value is all the words and whitespace contained within it. Some operations treat the words separately by dividing the list on whitespace, while others simply use the list as a unit.

When you enclose a section of content in braces within an iTL macro, that content becomes a list. The list is converted back into its component text (including whitespace) when (and if) incorporated into the final message content. (Any such whitespace may subsequently be reformatted by HTML presentation when the email is received.)

This occurs even if the list is deeply nested: {horse {cow {goat {dog {cat {bird {spider fly}}}}}}} This is not often something you intentionally create, but be aware that when such a list ends up in the final content of your email, its appearance is determined by "flattening" all the lists to remove the brace structure while preserving embedded whitespace.  See {\flatten ...} below.

iTL Operations

\identifier

As previously discussed, this is a variable reference. The identifier following the \ must begin with a letter, and may be followed by letters, digits, or underscores.

{\define \identifier EXPR}

This defines a new variable named \identifier to contain the value of iTL expression EXPR

Example: 

{\define \sport1 \"Football\"}

To refer to the variable later, use \ with its name as shown above.  This may appear in other content as {\ to create a macro, but the braces are not required inside another expression.

Example: 

{\sport1}

Result: Football

Example:  

{\if {\streq \sport1 \"Baseball\"} {Yogi Berra} {Vince Lombardi} }

Result: Vince Lombardi

{\set! \identifier EXPR}

This sets the existing variable \identifier to the value of the iTL expression EXPR.  Note the ! is part of the operator name.

Example: 

{\set! \sport1 \"Baseball\"}

Conditional Operators

Conditional syntax is supported by iTL. This includes And, Or, and If/Then statements. In conditional tests, all iTL values are true except for 0 (zero), the empty string \"\", and the empty iTL list {}, which are false.

{\and EXPR1 EXPR2 ... }

Evaluates each EXPR in turn, stopping if one yields a false value, and returns the value of the last EXPR it evaluates.

Example:

{\and 
  {\match \sport1 \"Football\" }
  {\match \sport2 \"Baseball\" }
}

{\or EXPR1 EXPR2 ... }

Evaluates each EXPR in turn, stopping when one yields a true value, and returns that true value if there is one, false otherwise.

Example: 

{\or 
  {\match \sport1 \"Football\" }
  {\match \sport2 \"Football\" }
}

{\not EXPR}

Reverses the truth value of EXPR.

{\cond {TEST1 THEN1a THEN1b ...} {TEST2 THEN2a THEN2b ...} ... } 

Evaluates each TEST in turn. If one yields a true value, evaluates each THENn in sequence and returns the value of the last one.

Example:

{\cond
  {
    {\match \interest \"Reading\"}
    {I Like Reading}
  }
  {
    {\match \interest \"Cooking\"}
    {I Like Cooking}
  }
  {
    {\match \interest \"Outdoor Activities\"}
    {I Like Outdoor Activities }
  }
  {
    1
    {Oops, nothing matched}
  }
}

{\if TEST THEN ELSE1 ELSE2 ...}

This evaluates TEST. If the result is true, it evaluates and returns THEN; otherwise it evaluates the ELSEs and returns the value of the last one.  In most usages, only a single ELSE case appears.

Example:

{\if
  {\match \sport1 \"Football\" }  \; TEST
  {<p>Check out the top football activities closest to you: www.example.com/football</p>}  \; THEN
  {<p>Your preferred activity is: {\var:sport1}. Check out the top sport activities closest to you: www.example.com/other_sports</p>} \; ELSE1
}

iTL for Strings

  • {\flatten EXPR1 EXPR2 ...}

Convert all the EXPRs to strings and combine them all into one string, preserving internal whitespace. For any of the following string operations, it is always safe to \flatten each operand first.

{\concat STR1 STR2 ...}

Concatenates the given strings.

Example: 

{\concat \"Thank you \" {\var:first_name} for your purchase today}

Result: Thank you, Johnforyourpurchasetoday

Notice how the spaces are considered only if enclosed by \"...\" because the \concat operation supersedes the usual whitespace preservation.

{\lc STR}

Converts all letters in STR to lowercase.

Example: 

{\lc \"IPOST Enterprise\"} 

Result: ipost enterprise

{\uc STR}

Converts all letters in STR to uppercase.

Example: 

{\uc \"iPost Enterprise\"} 

Result: IPOST ENTERPRISE

{\ucfirst STR}

Converts the first letter in STR to uppercase.

{\lcfirst STR}

Convert the first letter of STR to lowercase

{\streq S1 S2 ...}

True when S1, S2, etc. are identical strings.

Example: 

{\streq \"iPost\" \"ipost\"}

Result: an empty string (which is equivalent to FALSE in boolean tests) because of different case between the strings.

{\strge S1 S2 ...}

True when S1, S2, etc. are in lexically descending order, that is, S1 is lexically greater or equal to S2 and so on.

{\strgt S1 S2 ...}

Like \strge but none of S1, S2, etc. may be identical.

{\strle S1 S2 ...}

True when S1, S2, etc. are in lexically ascending order.

{\strlt S1 S2 ...}

Like \strle but none of S1, S2, etc. may be identical.

{\substr STR START [LEN] }

Extracts a substring from STR beginning at START, LEN characters long. Remember that the first position is 0.

- If START is negative, counts backward from the end of STR.

- If LEN is omitted, all characters to the end of STR are included.

Examples: Get the SKU from the URL 

{\define \url http://www.example.com/12345.html }
{\substr \url 23 5}     → 12345
{\substr \url -10 5}    → 12345

{\subst STR REGEX REPLACEMENT}

Replaces matches in STR for REGEX with REPLACEMENT. The modified string is returned.

Example: 

{\define \city \"      San Mateo   \" }
{\subst \city \"^[ \t]+\" City= }
STR: \"      San Mateo   \"
REGEX:  \"^[ \t]+\"
REPLACEMENT: City=

Result: \"City=San Mateo   \"

Notice that ^ in the REGEX means only the spaces beginning the string are substituted, the ones at the end of the string are kept.

{\match STR REGEX} / {\match \flags=FLAGS STR REGEX}

Finds matches in STR for REGEX and returns a non-empty list (true) when any are found or an empty list (false) otherwise.  When REGEX contains expressions inside balanced parentheses, the true-list contains the corresponding substrings from STR, otherwise the true-list is {1}. The most common value of FLAGS is \"i\" which makes the match case-insensitive.

Example: 

{\match \flags=i \city \"san ([a-z]*)\"}

Result: (true) {Mateo}

{\split STR REGEX [LIMIT]} / {\split \flags=FLAGS STR REGEX [LIMIT]}

Split STR at occurrences of REGEX into a list, which is returned. If optional LIMIT is supplied, the result will have no more than that many elements. The optional FLAGS are the same as in \match

{\sprintf FORMAT ARG ...}

Constructs a string out of the given 'sprintf' format and arguments.

Example:

{\define \price 10.2}
{\sprintf \"$%.2f\" \price}

Result: $10.20

{\strftime \format=FORMAT TIMESTAMP}

Format a date represented by TIMESTAMP in the specified FORMAT.

{\timestamp}

Return the current time, usually for use as the argument of \strftime or for a comparison

iTL for Arithmetic

{\add NUM ...}

Adds the given numbers.

{\subtract N1 N2 ...}

Subtracts its second and subsequent arguments from its first one. If only one argument is given, it returns its additive inverse.

{\divide N1 N2 ...}

Divides its arguments. If there's only one, it returns its multiplicative inverse.

{\multiply N1 N2 ...}

Multiplies its arguments.

{\numeq N1 N2 ...}

True if all arguments are numerically equal.

{\numge N1 N2 ...}

True if N1 > N2 > ... (monotonically decreasing).

{\numle N1 N2 ...}

True if N1 <= N2 <= ... (monotonically non-decreasing).

{\numlt N1 N2 ...}

True if N1 < N2 < ... (monotonically increasing).

{\max N1 N2 ...}

Returns the numerically largest argument

{\min N1 N2 ...}

Returns the numerically smallest argument.

{\random [N]}

Returns a random integer from 0 to N-1. If N is omitted, it returns a random floating-point number in [0, 1].

{\int NUM}

The integer portion of a floating point NUM.

iTL for URLS

{\link OPTIONS URL}

Produces a trackable link, meaning that the URL has been converted to a string that identifies the mailing and the recipient. When used with the appropriate parameters, {\link} can also be used to perform more advanced operations on a URL.

PLEASE NOTE: THIS iTL IS NOT NEEDED TO FORCE LINK TRACKING. iPOST WILL TRACK LINKS BY DEFAULT AS LONG AS LINK TRACKING IS ENABLED ON AN EMAIL SEND. In some cases automatic tracking does not produce a desired result, in which case {\link} provides finer control.

Options for \link

\name=VALUE

Specifying this option on {\link} will name the links as they are displayed in the Links tab and the Click by Link option in the Click Overlay in the Mailing Ticket.  Automatic tracking enables this when an anchor tag has a name= attribute, e.g. <a name=VALUE href=URL>...</a>

\blob_param=VALUE

When the URL is redirected, a query parameter VALUE is added to the URL. The value of the query parameter is the unique blob which identifies the contact and the mailing. 

Example: {\link \blob_param=id http://www.ipost.com

Result:  http://www.ipost.com?id=9z...

As a special case, if the VALUE is the single parameter / (slash) then the blob is appended as a trailing path.

Example: {\link \blob_param=/ http://www.ipost.com}

Result: http://www.ipost.com/9z...

\postprocess=METHOD \postprocess_args={ cgi1 key1 cgi2 key2 ... }

When the URL is redirected, the subroutine METHOD (see the list below) is called on the URL. For certain methods you must also specify \postprocess_args.  Note that iTL macros cannot be used as elements in the \postprocess_args list; all elements of that list are interpreted as literal strings.  Quoted strings with \"string\" may be used.

Only one METHOD may be selected for each {\link} macro.  These methods are available:

append_contact_data_param

At redirect time the target URL has contact data values appended to it. The values and the CGI parameters with which they'll be associated are defined in the \postprocess_args parameter. Please note that the data for the keys must have been imported into the iPost contact profile table.  Values from Custom Data Tables or API payloads are not available here.

- If a \postprocess_args keyN has the special value of recipient_addr then the email address of the contact is inserted for the associated cgiN.

- If a \postprocess_args cgiN has the special value of / (slash) then the value of its associated keyN is appended to the URL. Multiple / specifications result in multiple values added to the URL, forming a path.

- If a \postprocess_args cgiN has the special value of then the value of its associated keyN is used as the target URL. If multiple specifications appear, only the last one specified will be used.

Example: {\link \postprocess=append_contact_data_param \postprocess_args={fname firstname lname lastname} http://www.ipost.com}

Result: http://www.ipost.com?fname=Tim&lname=Enchanter

append_query_param

This works similarly to append_contact_data_param but appends query parameters literally rather than by looking up contact data.  Ordering is not preserved.

Example: {\link \postprocess=append_query_param \postprocess_args={FN Fred LN Flintstone} http://www.ipost.com}

Result: http://www.ipost.com?LN=Flintstone&FN=Fred

rewrite_url

This method requires \postprocess_args with argument/value pairs of {keyN stringN ...}. At redirect time, each keyN is looked up in the contact data and stringN is replaced with the corresponding value where it appears in the target URL.  This allows contact data to be inserted into other parts of the URL rather than only into the query parameters.

Example: {\link \postprocess=rewrite_url \postprocess_args={firstname fname lastname lname} http://lname.ipost.com/fname}

Result:  http://Enchanter.ipost.com/Tim

substitute_url

This method requires \postprocess_args with a single argument/value pair {key1 unused}. At redirect time, key1 is looked up in the contact data and its corresponding value is substituted entirely as the URL for redirection. Any additional arguments are ignored.

longlink

URLs have a character limit of 255. This method provides a workaround to that limit, allowing URLs to be as long as necessary.

This method requires \postprocess_args with a single argument/value pair of {url http://long.url.here}. Additionally, you must also include a "dummy URL". This dummy must be a valid URL but in practice the actual location of the dummy link does not matter as it gets substituted at redirect time with the long URL.

Example: {\link \postprocess=longlink \postprocess_args={url http://url/containing/more/than/255/characters} http://dummy/url/here}

really_expire

Causes all tracked links to resolve to the mailing expiration URL after the mailing expiration date has been reached.

Example: {\link \postprocess=really_expire http:/www.ipost.com}

{\nolink URL)

Produces a non-tracked URL in the email message.  When this iTL is used, the URL will not use the iPost redirect and any clicks for the URL will not be tracked.  

Example: {\nolink https://www.ipost.com}

Result: https://www.ipost.com

THIS EXPLICITLY DISABLES AUTOMATIC LINK TRACKING FOR ONE URL ONLY.

{\webscrape \url=URL HANDLING {FALLBACK}}

Retrieves the content of URL according to the specified HANDLING and returns it. In the event the URL cannot be retrieved, it returns FALLBACK content. The iPost Enterprise UI provides a helper wizard for building webscrape operations into your Email content.

HANDLING for \webscrape

These handling options may be omitted when not needed.

\detail=once

By default the URL content is fetched separately for each recipient at message send time. Using \detail=once causes the URL to be fetched during message validation (preview) and included in the content of every message.

\post={param1 value1 param2 value2 ...}

When the URL content should be accessed with an HTTP POST operation instead of the default HTTP GET, a list of alternating parameter names and corresponding values may be provided.

\track_urls=yes

The fetched content is analyzed for URL references and those are converted into tracked links. This is not a detailed analysis of the sort that occurs on message preview and may not discover all URLs in the content. Click events are recorded for reporting but details about the target URL and its position in the content are not. The default is not to track links in scraped content.

iTL for Custom Data Tables

{\lookup TABLE WHERE LIMIT ORDER {ACTIONS}}

The \lookup operator performs a simple real-time query on a named CDT table.

Required Arguments
TABLE \table=\"CDT_table_name\"
Name must be a fixed string
WHERE \where={ {COL1 VAL1} {COL2 VAL2} ...}
Case-insensitive equality
Optional Arguments
LIMIT \limit=NUMBER
Number of rows (up to 100)
ORDER \order={ {COL1 HOW} {COL2 HOW} ...}
HOW is \"asc\" or \"desc\"
{ACTIONS} List of iTL expressions
Evaluated for each row

If ACTIONS are provided, that iTL is evaluated for each row in the query result. The variable \row must be referenced to access the column values, which appear as a list in the same order as they are declared in the CDT table definition. The final value of \lookup is a list, one element per row, where each element is the result of the final ACTION taken on the corresponding row.

More commonly, ACTIONS are omitted. In this case the value of \lookup is a composite list, where each element is itself a list representing one row from the table. When there are no actions, it is also common to use \limit=1 so that only a single row is returned.

{\query \id=QID OPTIONS}

Runs the SQL query (defined in the Enterprise UI) chosen by QID. Returns structured data which must be processed by further iTL expressions. See iTL for Structured Data below, particularly \aref and \hashref. The default is to return a list where every element is itself a list representing one row from the SELECT statement of the query.

OPTIONS for \query

\limit=NUMBER

Determines the maximum number of rows returned from the query. The ordering of rows is determined by the query definition. Fewer rows may be returned, depending on the query. 

\key=FIELD_NAME

The result is returned as a hash keyed on the values of FIELD_NAME, which must be an output of the SELECT statement of the query definition. Row ordering is not preserved.

\bind={ { @var1 VALUE1 } { @var2 VALUE2 } ... }

Assigns each VALUE to the corresponding SQL @var which must appear in the SQL query definition. The @ sign must appear as a prefix to each SQL variable name.

\track_urls=yes

The value of each field in the returned row is examined for URL references and those are converted into tracked links. This is not a detailed analysis of the sort that occurs on message preview and may not discover all URLs in the content. Click events are recorded for reporting but details about the target URL are not. The default is not to track links. For more accurate tracking, place each URL in its own field and reference the field in an anchor (<a href={\field}>) tag in your Email content.

\detail=once

Perform the query during message validation (preview) or at the start of an automation, so that the results are fixed for every recipient during final personalization. Dynamic Variables should not be used with \bind in this case. The default is to run the query for each recipient during delivery.

iTL for Subroutines

{\define {\func PARAM1 PARAM2 ...} EXPR1 EXPR2 ...}

Defines a subroutine and assigns it the identifier \func.  When the subroutine is invoked, its arguments will be assigned to the parameters PARAM1, PARAM2, etc,, and the EXPRs evaluated in the resulting context. The value will be the value of the last EXPR.

Each PARAM is one of the following:

- \parm - This identifies a positional parameter

- \=name - This identifies a named parameter

- \&rest - All remaining arguments are collected as a list named \rest.  Only one use of this may appear in the PARAM... list.

Example:

{\define {\Nth \num \&words}
  \; return element number \num from words
  {\aref \words \num}}
{\Nth 4 fly spider bird cat dog goat cow horse}

Result: dog

{\lambda {PARAM1 PARAM2 ...} EXPR1 EXPR2 ...}

Creates an anonymous subroutine.  PARAMs are as described above.

Example:

{{\lambda {\num \&words} {\aref \words \num}}
  \; works like \Nth above, but
  \; without creating a named function
  5 fly spider bird cat dog goat cow horse}

Result: goat

iTL for Structured Data

{\append LIST ...}

Given one or more lists, it combines their top-level elements into a single list.

{\apply FN ARG1 ARG2 ... ARGn}

Calls iTL function FN on given arguments. If ARGn is a list, then it's interpreted as a list of arguments. (Use \funcall if you don't want this behavior.)

Any named parameters (\name=value) passed to \apply are passed along to FN.

{\aref LIST N}

Returns the Nth element of the iTL LIST

N is 0-based.

{\aset LIST N VAL}

Sets the Nth element of LIST to VAL.

{\foreach FN LIST}

Returns a list resulting from calling FN on each member of LIST.

{\funcall FN ARG1 ARG2 ...}

Calls iTL function FN on the given arguments. Any named parameters passed to \funcall are passed along to FN.

{\length OBJ}

Returns the length of OBJ — in elements, if OBJ is a list, or in characters, if OBJ is a string.

{\list ARG1 ARG2 ...}

Makes a iTL list out of the given arguments.

{\listp OBJ}

True if OBJ is a iTL list.

{\pop LIST}

Removes the last element from LIST and return it.

{\push LIST OBJ1 OBJ2 ...}

Adds the given OBJs to the end of LIST.

{\shift LIST}

Removes the first element of LIST and returns it.

{\subseq LIST START [LEN]}

Extracts a sublist from LIST beginning at START , LEN elements long.

If START is negative, counts backward from the end of LIST

If LEN is omitted, all elements to the end of LIST are included.

{\unshift LIST OBJ1 OBJ2 ...}

Adds the given OBJs to the beginning of LIST.

{\hashdel HASH KEY}

Deletes from HASH the entry with the given KEY.

{\hashkeys HASH}

Returns the keys of HASH, a iTL hash, as an iTL list.

{\hashp OBJ}

True iff OBJ is an iTL hash.

{\hashref HASH KEY}

Returns the element of HASH whose key is KEY.

{\hashset HASH KEY VALUE}

Sets the entry in HASH with key KEY to the given value.

{\hashtest HASH KEY}

True if HASH contains an element with the given key.

{\mkhash [KEY1 VAL1 KEY2 VAL2 ...]}

Makes a new iTL hash, initializing it with the optional key-value pairs.  his is usually assigned to an identifier:   {\define \coaches {\mkhash Football Vince Baseball Yogi} }

iTL for Content Management

These macros are most often generated by use of the content management tools in the iPost Enterprise UI, and rarely need to be written by hand, but are included here for reference.  

Note that many of these macros are disallowed, or may behave differently, when invoked as a macro from SSJS.

{\abort REASON}

Immediately cease processing the message for the current recipient, logging the REASON text. This should be used only as an EXPR (not as a TEST) in an \if or similar conditional.  Beware of iTL's leftmost-innermost expression ordering when using this in other contexts.

{\itl_snippet \id=SNIPID}

Retrieve and insert the snippet identified by SNIPID.

{\itl_header \id=HEADID}

Retrieve and insert the header identified by HEADID.

{\itl_footer \id=FOOTID}

Retrieve and insert the footer identified by FOOTID.

{\itl_dynamic \id=DYNID}

Retrieve and  insert the dynamic content identified by DYNID.

{\itl_rss \id=RSSID}

Retrieve and insert the most recently cached articles for the RSS feed identified by RSSID.

{\document_segment \segment=SEGID}

At validation time, a reference to a snippet, header, footer, dynamic content, or webscrape content may be compiled into an internal format called a document segment. This macro retrieves and inserts such a segment by SEGID.

{\current_segment}

Returns the SEGID for the document segment that is being processed at the current content position. Usually used for comparisons.

{\recipient_segment}

When using A/B subject testing, this returns the A/B segment identifier assigned to the current recipient. This is not a SEGID for use with \document_segment.

iTL for Server-Side Javascript

{\javascript \detail=RUNTIME \"CODESTRING\"}

Alternate syntax for including SSJS in contexts that do not support HTML parsing, such as plain-text documents.  Equivalent to

<script type="itl/javascript" style="--detail: RUNTIME">
 CODESTRING
</script>

The CODESTRING must form an iTL string-literal \"...\" token, so use care with quoted strings in the SSJS.

{\jsget VARIABLE}

Retrieve a value assigned by SSJS itl.set(VARIABLE, value)

iTL Conveniences

{\recipient_addr}

The email address to which the current message is being delivered.

{\client_name}

The official name assigned to the current client instance. Mostly useful in Template Email Content when shared among business units having different names.

{\client_sender_addr}

The email address assigned to the current client instance or sender domain.

{\sender_postal_addr}

The physical address assigned to the current client instance or sender domain.

{\virtual_domain}

The delegated domain assigned to the current client instance or sender domain. References to this are usually inserted automatically as part of link tracking. 

{\wrap \margin=WIDTH OPTIONS TEXT}

Primarily for formatting plain-text messages, this macro accepts a paragraph of TEXT and re-folds it to fit in WIDTH characters (monospace assumed).  Line breaks in TEXT are preserved.  Link tracking does not automatically apply within wrapped TEXT, so use {\link ...} as necessary; note however that such links may cause the text to overflow the WIDTH.  \margin may be omitted in which case 72 characters is used.

OPTIONS for \wrap

\prefix=PREFIX

Append the text given by PREFIX to every line of the paragraph, before calculating the WIDTH.  Usually used to insert whitespace for plain-text indentation.

\prefix1=INDENT

The INDENT text is inserted before the first line of the paragraph TEXT, in place of the PREFIX.  May be used to create hanging indents or paragraphs with only the first line indented.

{\fill \margin=WIDTH OPTIONS TEXT}

Like \wrap except that line breaks in TEXT are replaced with spaces before wrapping.

{\opt_out TEXT}

Inserts a paragraph of opt-out instructions. If TEXT is empty, a default paragraph is used, which includes a link to the iPost-hosted preferences form. Otherwise TEXT should include whatever URLs are intended to be used for managing recipient preferences.

{\submit_time}

In notification journeys, the timestamp at which the recipient was injected into the journey.

{\submit_ip}

In notification journeys, the IP address associated with the recipient's browser at the time of injection.

{\notify_new_email}

In notification journeys for change of email address, the new address after the change.

{\notify_old_email}

In notification journeys, the old old email address before the change.