Table of Contents

Description

“Scriptlets” is the name of our programming language used within Maileon newsletters to realize extensive requirements on data processing and output. Scriptlets allow for example generating random numbers or UUIDs for each contact within a sendout in order to attach it to some link. It allows generating an (MD5) hash of data like the email address or encrypt data with some given key and supports complex processing of data like parsing a string as a datetime object, adding 7 days and printing it in some other format. Also accessing external data sources for each individual contact is possible in order to e.g. display individual products for each contact.

Thus, Scriptlets support a huge number of language elements and even if it is not possible to create an infinite loop, you can use loops, e.g. when iterating over the items of some shopping cart in order to calculate the overall sum or to display the items in a newsletter.

The formal description is provided as BNF in the next section, however, most readers will benefit at the beginning more of some unformal description or the examples later on. Scriptlets are always wrapped in double square brackets [[ ]]. Inside the brackets, a Scriptlet is started with a “%” sign to avoid mixing up regular Maileon-Mergetags and Scriptlets. For Scriptlets a preorder syntax has been chosen, this means that the operator is in the beginning of an expression and the parameters follow behind, separated by a whitespace “ “. If an parameter is an expression with some operator itself, it has to be wrapped in single round brackets ().

Simple examples:

[[ % 'Hello world!']]
[[ % md5 (contact 'EMAIL')]]

For date and time formats please refer to https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/text/SimpleDateFormat.html

Formal Description

 This section defines the BNF of the language elements.

<expr>                    ::= <void_expr> | <none_void_expr>
<void_expr>               ::= <conditional_statement> | <foreach_statement>
<conditional_statement>   ::= <if_statement> | <elseif_statement> | <else_statement> | <endif_statement>
<if_statement>            ::= "if" {logical_expr>
<elseif_statement>         ::= "elseif" {logical_expr>
<else_statement>          ::= "else"
<endif_statement>         ::= "endif"
<foreach_statement>        ::= <foreach_expr> | <end_foreach> | break
<foreach_expr>            ::= "foreach" <var_expr> "in" <sequence_expr>
<end_foreach>              ::= "endforeach"
<none_void_expr>          ::= <typed_expr> | <untyped_expr>
<typed_expr>              ::= <string_expr> | <date_expr> | <datetime_expr> | <logical_expr> | <numeric_expr> | <sequence_expr>
<untyped_expr>            ::= <assign_expr> | <hash_expr> | <var_expr>
<assign_expr>              ::= "set" <var_expr> <none_void_expr>
<var_expr>                ::= "$" litteral
<string_expr>             ::= string | <string_function> | <untyped_expr>
<numeric_expr>            ::= number | <numeric_function> | <untyped_expr>
<logical_expr>            ::= boolean | <logical_function> | <untyped_expr>
<sequence_expr>           ::= sequence | <sequence_function> | <untyped_expr>
<date_expr>               ::= <date_function> | <untyped_expr>
<datetime_expr>           ::= <datetime_function> | <untyped_expr>

Language Elements

The 'mine' Function

String Functions

Logical functions

As Maileon uses a three state value for Booleans (not set, true or false), these methods define a fallback behavior, which is added in [brackets] behind the expression. They will return this result, if e.g. a custom field is not set. Methods without annotation will fail if the field is empty, so a check for existence is mandatory.

Numeric Functions

Sequence Functions

Object Functions

Date Functions

Datetime Functions

External Data

Maileon can retrieve external data, either as JSON or plain HTML. The following facts and restrictions are valid for both features.

Maileon uses caching strategies to reduce the amount of request. Please make sure that the server always returns the same response for the same request within one sendout. As URLs can contain variables it might result in a lot of different URLs and thus, a lot of requests. Make sure your server can process the request fast enough as it will delay the sendout process. If a service times out, the mailing(s) the response was meant for are not processed any further and are reported as “failed sendouts”.

Request Type

GET

Number of parallel requests

bis zu 40

Request Cache

Per thread and per “working packet” (= 5.000 contacts)
So even if the URL is always the same, there can be several requests

Response Code

200
Server must respond with Status 200

Redirects

Not allowed
Please make sure to use no redirects

Authorization

Optional, Basic Auth in URL format
Example: https://user:password@domain/path...

Maximum Response Size

3 MB

Timeout

5 Seconds
Please be aware that the default response time should be a few milliseconds, only.

URL Restrictions

Please be aware that URLs like “localhost” or “127.0.0.1” neither make sense, nor are accepted

External JSON

Feed Structure

External JSON can be used to request data from external systems that is processed and rendered into the mailing. Please make sure that you do not return an array, directly, always return an object and there an attribute with an array content. I.e. do not return

[
   {
      "product_id":1,
      ...
   },
   {
      "product_id":2,
      ...
   }
]

But wrap it in an object with a named attribute, e.g.:

{
   "recommendations": [
      {
          "product_id":1,
          ...
      },
      {
          "product_id":2,
          ...
      }
   ]
}

Syntax for retrieving data

[[EXTERNAL-JSON|{varName}|"{url_with_personalization}"]]

{varName} is a free choosable name for the variable, the content is available in, later. It must start with a character. {url_with_personalization} is the url with protocol (https://) and personalizations e.g. from contactfields need to be in Mergetag-Syntax with only a single bracket, e.g. the E-Mail-Hash would be: [MD5|CONTACT|EMAIL]

Syntax Example

[[EXTERNAL-JSON|myData|"http://www.xqueue.com/[CONTACT|jsonfile] "]]

In this case the data of the “stream” will be available in variable “myData” and will submit some path parameter from a customfield called “jsonfile”. Variables can of course also used as query parameters (sometimes referred to as GET parameters).

Data Usage

From here, Scriptlets can be used to access the values using “ext_json” method, e.g.:

[[% ext_json 'myData' 'recommendations[1].product_id']]

To save the array into variable myVar:

[[% set $myVar (ext_json 'myData' 'recommendations')]]

To save the first array element from myVar (example above) into variable myElement

[[% set $myElement (item $myVar 0)]]

Or simply use loops to display all elements

[[
  % foreach $recommendation in $myVar
    % property $recommendation 'product_id'
  % endforeach
]]

External HTML

The HTML provided by an external service provider will be included in Maileon as returned. Make sure to not return invalid HTML or HTML that causes display problems in Mail clients.

Please be aware that dynamic fields within returned HTML are not filled by Maileon. In other words: if a mergetag like [[CONTACT|FIRSTNAME]] is included in the returned HTML, it will not be processed by Maileon.

Syntax for retrieving data

Syntax: [[EXTERNAL-RAW|"http://www.xqueue.com/[CONTACT|jsonfile]"]]

Examples

Multiple Statements

[[
     % (contact 'FIRSTNAME') % ''
     %
           (
                contact
                'custom property'
                'default value'
           ) % ' '
     % (transaction 'some.path') % ' '
     # comment
     % set $var (join (transaction 'some.list' ','))
     % $var
]]

Comments

[[
     # comment 1
     # comment 2
]]

Hashes

[[
     % contact 'FIRSTNAME'
     % contact 'FIRSTNAME' 'default\'value'
     % mailing 'SUBJECT'
     % account 'NAME'
     % transaction 'some.property'
]]

Standard hashes

As SUBJECT or NAME are standard values for mailings, you can also access own custom values of mailings with just specifying the key name, e.g. [[ % mailing 'test' ]]

[[
     % email
     % firstname
     % lastname
     % title
     % salutation
]]

Maps

If the value of $var is a map (key-value pairs) then you can access some value by calling:

[[
  % (property $var 'name of the property')
]]

Example: Shoppingcart

[[
  % set $items (transaction 'cart')
  % foreach $item in $items
  %   property $item 'name'
  % endforeach
]]

Primitives

[[
     % to_string true
     % 'string'
     % -12.34
]]

Output: truestring-12.34

Variables

[[
     % set $myVar 'a'
     % set $myVar2 (upper_case $myVar)
     % $myVar
     % $myVar2
]]

Output: aA

Dates, Datetimes

[[
     % set $myVar
           (to_datetime
                (transaction 'order.date')
                'yyyy-MM-dd hh:mm:ss'
           )
     % datetime_to_string $myVar 'EEEE dd.MM.yyyy' 'fr'
]]

 Current date and time

[[ % date_to_string (now) 'dd.MM.yyyy HH:mm:ss' 'de' ]]

 Print date of yesterday

[[ % date_to_string (time_to_date (sub (date_to_time (now)) 60000000)) 'dd.MM.yyyy' 'de' ]]

Sequences

[[
     % set $seq1 {'a', 'b', 'c'}
     % set $seq2 {'a', -1.2, true, (contact 'property'), $seq1}
     % set $seq3 (seq_add $seq1 'd')
     % set $seq3 (seq_add_all $seq1 $seq3)
     % join $seq3 'x'
]]

Output: axbxcxaxbxcxd

Conditional Statements

[[
     % if (equals 'Max' firstname)
          %    'a'
     % elseif (equals 'Erika' firstname)
          %    'b'
     % elseif
          (or
               (and $boleanVar (contact 'bool'))
               (negate $booleanVar)
          )
          %    'c'
     % else
          %    'd'
     % endif
]] 

Loops

[[
     % set $seq {{'a', 'b'}, {'c', 'd'}, {'e', 'f'}}
     % foreach $i in $seq
     %    foreach $j in $i
     %          $j
     %    endforeach
     % endforeach
     % foreach $i in {1, 2, 3}
     %    $i
     %    if (eq $i 2)
     %          break
     %    endif
     % endforeach
]]

Output: abcdef12

Usecase Examples

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Changelog

 

Version 1.7

Version 1.6 08.04.2022

Version 1.5 26.10.2021

Version 1.4 (27.09.2019)

Version 1.3 (07.02.2019)

Version 1.2 (28.03.2017)

 

Version 1.1 (29.07.2016)