en:otml

How do I develop email templates for promio.connect?

The following document provides technical information for the development of email templates for promio.connect.

General information

  • Special characters must use XML-conform entities:
    • "
    • &
    • '
    • <
    • >
    • for all other entities, you have to use decimal syntax; e.g., use   instead of  
  • UTF-8 4-byte characters are not supported at the moment. You can check the byte length with several tools, e.g., UTF-8 Tool.
  • The length of lines in the source code must not exceed 700 characters.

If you use an IDE to develop the template, use the following namespaces for correct syntax highlighting:

<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xmlns:pme="http://www.promio.net/pmeType"
      xmlns:pm="http://www.promio.net/pmType">
</html>

OTML

OTML is an extension of the HTML standard, specifically created for usage in promio.connect's email editor. Because of this, an understanding of HTML and CSS is mandatory.

OTML serves the cause to make designated parts of an email editable. The global structure of the email will not be affected. At first, the email developer creates the email as usual. After this is done, all intended parts can be made editable with the usage of OTML.

The OTML elements are separated into two namespaces: pm and pme:

  • pm elements are used for the automatic generation or integration of content, such as the table of contents or data sources.
  • pme elements are user-editable elements, e.g., single-line and multi-line editors.

Editable Title

If you want the user to be able to edit the title of the mail, add the attribute editable=“true” to your <title> tag. This has mostly only an effect if the email is opened in its stand-alone browser version.

Example

<!DOCTYPE html>
<html>
  <head>
    <title editable="true">E-Mail Title</title>
  </head>
  <body>
    <div>
      <a href="http://system.promio-mail.com/view/" target="_blank">
        Please click here if you can't read this E-Mail.
      </a>
    </div>
  ...

Repeater

A repeater is represented by the OTML tag <pme:repeater />.

A repeater element defines an area of repeating blocks and must contain one or more <pme:layout /> elements. Each layout can then be added to the email by the user via a selection list.

The repeater element can hold one or more <pme:repeatercontent /> elements.

Attribute Type Required Description
title string No Title of the repeater. This is useful if you use more than one repeater in your template.

Example

<pme:repeater>
 
	<pme:layout name="Layout 1">
	<table border="0" cellpadding="0" cellspacing="0" width="100%">
		<tr>
			<td>Layout 1</td>
		</tr>
	</table>
	</pme:layout>
 
	<pme:layout name="Layout 2">
	<table border="0" cellpadding="0" cellspacing="0" width="100%">
		<tr>
			<td>Layout 2</td>
		</tr>
	</table>
	</pme:layout>
 
	<pme:repeatercontent>
	<table border="0" cellpadding="0" cellspacing="0" width="100%">
		<tr>
			<td>Layout 1</td>
		</tr>
	</table>
	</pme:repeatercontent>
 
</pme:repeater>

Layout

A layout is represented by the OTML tag <pme:layout />.

A layout element contains a template, which can be added to the email. It's a sub-element of the <pme:repeater> element and can be added multiple times.

Attribute Type Required Description
name string Yes Unique name for the layout

Example

<pme:repeater>
 
	<pme:layout name="Layout 1">
	<table border="0" cellpadding="0" cellspacing="0" width="100%">
		<tr>
			<td>Layout 1</td>
		</tr>
	</table>
	</pme:layout>
 
</pme:repeater>

Repeater content

A repeater content is represented by the OTML tag <pme:repeatercontent />.

The repeater content determines a pre-defined part of a <pme:repeater /> element and acts exactly like a <pme:layout /> element. It's a sub-element of the <pme:repeater> element and can be added multiple times. With the <pme:repeatercontent /> element it's possible to pre-fill a <pme:repeater />.

Example

<pme:repeater>
 
	<pme:layout name="Layout 1">
	<table border="0" cellpadding="0" cellspacing="0" width="100%">
		<tr>
			<td>Layout 1</td>
		</tr>
	</table>
	</pme:layout>
 
	<pme:repeatercontent>
	<table border="0" cellpadding="0" cellspacing="0" width="100%">
		<tr>
			<td>Layout 1</td>
		</tr>
	</table>
	</pme:repeatercontent>
 
</pme:repeater>

Preheader

A preheader is represented by the OTML tag <pme:preheader />.

A preheader is the preview text which is shown beneath the sender in most email clients. During the build process of the email, the content of the preheader element will be put directly after the <body> tag. All tracking pixels provided by promio.connect will be embedded after the preheader. This way, there is no HTML source code visible to the end-user.

<pme:preheader>This is the preheader text.</pme:preheader>

Singleline

A singleline element is represented by the OTML tag <pme:singleline />.

The singleline element offers a simple text input field and is mostly used for short texts like a headline.

Attribute Type Required Description
data-pmclass string No The value will be set as class on the link element, if a link is added to the singleline element.
label string No The title of the element, which is shown in the edit view.
linkable boolean No If linkable is false, its not possible to add or change a link around the singleline element.
pmtoctitle string No Title for entry inside the TOC.<br>Set a value to preallocate a title or leave it blank to make it possible, to set a TOC title if desired.
max-length integer No Maximum lenght of characters. The user will not be able to exceed this limit.

Example

<pme:singleline label="Headline" max-lenght="30">My Headline</pme:singleline>
 
<a class="link" href="https://www.promio.net" target="_blank">
	<pme:singleline data-pmclass="link" label="Link">Click me</pme:singleline>
</a>

Multiline and Multiline-Config

A multiline element is represented by the OTML tag <pme:multiline />.

The multiline element offers an advanced text and HTML editor based on CKEditor 4. It is mostly used for long texts or where HTML input is desired.

Attribute Type Required Description
label string No The title of the element, which is shown in the edit view.
linkable boolean No Make it possible to add a link around the editor content. If you enable this, we recommend that you use a special multiline-config for these editors in which the link button is removed from the toolbar.
pmtoctitle string No Title for entry inside the TOC.<br>Set a value to pre-allocate a title or leave it blank to make it possible, to set a TOC title if desired.
max-length integer No Maximum lenght of characters. The user is able exceed this limit, but a warning will be shown.
config string No Name of the multiline-config, that should be used for this editor.

Example

<pme:multiline label="Text">Lorem ipsum dolor sit amet</pme:multiline>

The multiline editor can be configured with a multiline-config element, which is represented by the OTML tag <pm:multiline-config>.

Attribute Type Required Description
name string Yes The name of the config element.
default boolean No Set to true, if this config should be used for all pme:multiline elements, where no config is specified by name.

The content of a multiline-config must be a CKEditor configuration in JSON format.

Example

<pm:multiline-config default>
{
  "forcePasteAsPlainText": true,
  "toolbar": [
	{
	  "name": "basicstyles",
	  "items": [
		"Bold",
		"Italic",
		"-",
		"Subscript",
		"Superscript",
		"-",
		"RemoveFormat"
	  ]
	},
	{
	  "name": "links",
	  "items": [
		"Link",
		"Unlink"
	  ]
	},
	{
	  "name": "insert",
	  "items": [
		"Table",
		"SpecialChar"
	  ]
	},
	{
	  "name": "clipboard",
	  "groups": [
		"clipboard",
		"undo"
	  ],
	  "items": [
		"Cut",
		"Copy",
		"Paste",
		"-",
		"Undo",
		"Redo"
	  ]
	},
	{
	  "name": "promio",
	  "items": [
		"promioPersFunc",
		"promioTemplates"
	  ]
	},
	{
	  "name": "document",
	  "items": [
		"Source"
	  ]
	},
	{
	  "name": "tools",
	  "items": [
		"Maximize"
	  ]
	}
  ]
}
</pm:multiline-config>
 
<pm:multiline-config name="linkable-editor">
{
  "forcePasteAsPlainText": true,
  "toolbar": [
	{
	  "name": "basicstyles",
	  "items": [
		"Bold",
		"Italic",
		"-",
		"Subscript",
		"Superscript",
		"-",
		"RemoveFormat"
	  ]
	},
	{
	  "name": "insert",
	  "items": [
		"Table",
		"SpecialChar"
	  ]
	},
	{
	  "name": "clipboard",
	  "groups": [
		"clipboard",
		"undo"
	  ],
	  "items": [
		"Cut",
		"Copy",
		"Paste",
		"-",
		"Undo",
		"Redo"
	  ]
	},
	{
	  "name": "promio",
	  "items": [
		"promioPersFunc",
		"promioTemplates"
	  ]
	},
	{
	  "name": "document",
	  "items": [
		"Source"
	  ]
	},
	{
	  "name": "tools",
	  "items": [
		"Maximize"
	  ]
	}
  ]
}
</pm:multiline-config>
 
/* This editor uses the default config */
<pme:multiline>Text</pme:multiline>
 
/* This editor uses the "linkable-editor" config */
<pme:multiline config="linkable-editor">Text</pme:multiline>

Image

Images have no special OTML element representation. Instead they use the standard HTML <img /> tag with extended attributes.

Attribute Type Required Description
pmedit boolean No If pmedit is true, the image is editable.
pmscale string No Possible values: crop / height / width
pmscaleheight integer No Use an alternate height instead of the one defined in the height attribute. This is useful for presentation on HiDPI / Retina displays.
pmscalewidth integer No Use an alternate width instead of the one defined in the width attribute. This is useful for presentation on HiDPI / Retina displays.
pmtoctitle string No Title for entry inside the TOC.<br>Set a value to preallocate a title or leave it blank to make it possible, to set a TOC title if desired.

Values for pmscale

Value Description
crop
height Resize the image to the defined height. The width is calculated proportional to the dimensions of the original image.
width Resize the image to the defined width. The height is calculated proportional to the dimensions of the original image.

Example

<img alt="Image" height="200" src="image.png" pmedit="true" pmscale="crop" width="200" />
 
<img alt="Image" height="50" src="image.png" pmedit="true" pmscale="height"  />
 
<img alt="Image" src="image@3x.png" pmedit="true" pmscale="width" pmscalewidth="600" width="200" />

Appointment

To provide a link to an appointment, you can use the <pme:appointment> element. Based on the inserted data, an iCal calendar file will be generated.

Attribute Description
text Text that is visible in the email
summary Title of the appointment
organizerName Name of the appointments organizer
organizerEmail Email of the appointments organizer
dateTimeStart Start date and time of the appointment
dateTimeEnd End date and time of the appointment
location Location of the appointment
description Description of the appointment
<pme:appointment>
 
</pme:appointment>

TOC

A TOC (table of contents) is represented by the OTML tag <pm:toc />.

The TOC element is used to automatically generate a table of contents based on the values and the order of used pmtoctitle attributes.

The TOC elements requires exactly one <pm:tocitem /> element, which represents the the value of the processed pmtoctitle attribute. The complete content of the TOC element is repeatedly inserted for each pmtoctitle attribute with a value.

Example

Template
<ul>
	<pm:toc>
		<li><pm:tocitem /></li>
	</pm:toc>
</ul>
 
<pme:singleline pmtoctitle="Headline 1">Content</pme:singleline>
<pme:singleline pmtoctitle="Headline 2">Content</pme:singleline>
Rendered code
<ul>
	<li>
		<a href="#link_to_anchor_1">Headline 1</a>
	</li>
	<li>
		<a href="#link_to_anchor_2">Headline 2</a>
	</li>
</ul>

External data sources

External data sources make it possible to embed content from RSS feeds into an email.

The setup of external data sources is individually realized by promio.net GmbH. If you are interested in the usage, please contact our support team via ticket.

Source

The source element is represented by the OTML tag <pm:source />.

It serves as wrapper for the different source items and may contain one or more <pm:sourceitem /> elements.

Attribute Required Type Description
pmedit No boolean If true, users are allowed to change datasources.

Source item

A source item is represented by the OTML tag <pm:sourceitem />.

It serves as the connection between the email and the setup data source.

Attribute Required Type Description
name Yes string Unique name of the data source.
refreshmode Yes string Possible values: build / delivery
Values for refreshmode
Value Description
build Refresh data source on build of the email.
delivery Refresh data source before sending the campaign.

Data section

A data section is represented by the OTML tag <pm:datasection />.

Data sections are used to fill the template with content from the data source with the help of data items. Each data section must contain at least one <pm:data /> element.

Attribute Required Type Description
source Yes string The name of the datasource.
items No json A json object. Use one entry per data item inside the current data section, to define, how the next data item will be chosen.<br>If no option is chosen, it defaults to “next”.

With the items attribute, it is possible to define the selection of content for each data item.

Value Description
(itemId) Choose a data item on the base of its unique id.
next Choose the next data item in the list. This is the most used option.
rand Choose a random data item.
Example

If you want to set the content of the first data item to the unique id 12345 and random data for the second one, use this string:

{ 1: 12345, 2: "rand" }

Data item

A data item is represented by the OTML tag <pm:data />.

Data items are placed inside a data section. Each one represents one record from the data source.

Inside a data item, it's possible to use the placeholder [pm:item:field_name] to get access to a field of the data source record. With the cut function, it is also possible, to shorten the content of a placeholder to a specified amount of characters.

E.g.: [cut([pm:item:title], 20)] shortens the title to a maximum of 20 characters.

It's only possible to access each data item one time. If you want to access the same item multiple times, it is necessary to use multiple data sources with the same content. In this case, please contact our support team via ticket.

Example

Sample data source "Top 10 Products"
id title price image link
123 Smartphone 350.00 € smartphone.jpg www.sample.com/shop?productid=123
124 Watch 150.00 € watch.jpg www.sample.com/shop?productid=124
125 Powerbank 50.00 € powerbank.jpg www.sample.com/shop?productid=125
Template code
<html>
<head>
	<pm:source pmedit="true">
		<pm:sourceitem refreshmode="build" name="Top 10 Products"></pm:sourceitem>
	</pm:source>
</head>
<body>
	<pm:datasection source="Top 10 Products" items='{ "1": "124", "2": "next", "3": "next" }'>
 
		<pm:data>
			<table>
				<tr>
					<td>
						<a href="[pm:item:link]" target="_blank">[pm:item:title]</a>
					</td>
				</tr>
				<tr>
					<img alt="[pm:item:title]" src="[pm:item:image]" width="200">
				</tr>
				<tr>
					<td>Price: [pm:item:price]</td>
				</tr>
			</table>
		</pm:data>
 
		<pm:data>
			<table>
				<tr>
					<td>
						<a href="[pm:item:link]" target="_blank">[pm:item:title]</a>
					</td>
				</tr>
				<tr>
					<img alt="[pm:item:title]" src="[pm:item:image]" width="200">
				</tr>
				<tr>
					<td>Price: [pm:item:price]</td>
				</tr>
			</table>
		</pm:data>
 
 
		<pm:data>
			<table>
				<tr>
					<td>
						<a href="[pm:item:link]" target="_blank">[pm:item:title]</a>
					</td>
				</tr>
				<tr>
					<img alt="[pm:item:title]" src="[pm:item:image]" width="200">
				</tr>
				<tr>
					<td>Price: [pm:item:price]</td>
				</tr>
			</table>
		</pm:data>
 
	</pm:datasection>
</body>
</html>
Rendered email code
<html>
<body>
	<table>
		<tr>
			<td>
				<a href="www.sample.com/shop?productid=124" target="_blank">Watch</a>
			</td>
		</tr>
		<tr>
			<img alt="Watch" src="watch.jpg" width="200">
		</tr>
		<tr>
			<td>Price: 150.00 €</td>
		</tr>
	</table>
 
 
	<table>
		<tr>
			<td>
				<a href="www.sample.com/shop?productid=125" target="_blank">Powerbank</a>
			</td>
		</tr>
		<tr>
			<img alt="Powerbank" src="powerbank.jpg" width="200">
		</tr>
		<tr>
			<td>Price: 50.00 €</td>
		</tr>
	</table>
 
	<table>
		<tr>
			<td>
				<a href="www.sample.com/shop?productid=123" target="_blank">Smartphone</a>
			</td>
		</tr>
		<tr>
			<img alt="Smartphone" src="smartphone.jpg" width="200">
		</tr>
		<tr>
			<td>Price: 350.00 €</td>
		</tr>
	</table>
 
</body>
</html>

If-conditions within data items

It is possible to use If-conditions within data items.

<pm:datasection source="Datasource 1" items='{ 1: "rand" }'>
 
	<pm:data>
		<table>
			<tr>
				<td>
					<a href="[pm:item:link]" target="_blank">[pm:item:title]</a>
				</td>
			</tr>
			<tr>
				<img alt="Product" src="[pm:item:image]" width="200">
			</tr>
			<tr>
				<td>
					 <pm:dynamic>
						<pm:if>
							<pm:condition>
								[pm:item:priceReduced] == ""
							</pm:condition>
							Price: [pm:item:price]
						</pm:if>
						<pm:else>
							Price: [pm:item:priceReduced]<br />
							instead of <span style="color: #f00; text-decoration: line-through;"[pm:item:price]</span>
						</pm:else>
					</pm:dynamic>
				</td>
			</tr>
		</table>
	</pm:data>
 
</pm:datasection>

External content

pm:include-url-content is a very special tag. Use it to include the source code of a website into your email.

It is also possible to use this tag in the subject of an email.

Attribute Type Required Description
url string Yes The URL of the content you want to include.
title boolean No If true, the content of the URL's title tag is returned.

Example

As content of an email:

<pm:include-url-content url="https://www.promio.net/my-template.html">
	This default text is only visible if the url does not return any content.
</pm:include-url-content>

As subject:

<pm:include-url-content url="https://www.promio.net/my-template.html" title="true">
	This default title is only visible if the url does not return any content.
</pm:include-url-content>

CSS

Automatic transformation from CSS to inline CSS

CSS from a <​style> ​block can automatically ​be transformed to Inline ​CSS. For more details on the matter refer to the cssinline and cssinlinetype options in config_tags

User editable CSS

To give users the freedom to edit the CSS, there are some prerequisites:

  • The style tag must use the id pn-js-css-editor. Only one style tag with this id is allowed.
  • Each selector must use a comment block with the descriptors @nav, @navItem and @info.
    • @nav represents the category inside the CSS editor and groups the different @navItem elements.
    • @navItem represents the element inside the category. This name must be unique for all CSS selectors within the same @nav category.
    • @info serves as decription for the @navItemelement.
<style id="pn-js-css-editor" media="all" type="text/css">
	/*
	@nav Article
	@navItem Text
	@info Change the font settings of article texts.
	*/
	.article-text {
		/*@edit*/color: #000;
		/*@edit*/font-family: Arial, Helvetica, sans-serif;
		/*@edit*/font-weight: 300;
		/*@edit*/font-size: 13px;
		/*@edit*/line-height: 1.4;
		/*@edit*/text-align: left;
		/*@edit*/text-decoration: none;
		/*@edit*/text-transform: none;
	}
 
	/*
	@nav Article
	@navItem Link
	@info Change the font settings of links inside article texts.
	*/
	.article-link {
		/*@edit*/color: #000;
		/*@edit*/font-weight: 300;
		/*@edit*/text-decoration: none;
	}
</style>

Dynamic content

Placeholders

With the help of placeholders, it's possible to access the fields of your user data or include dynamic content.

You can access each user data field if you place a $ character in front of the field name. E.g., access the field name with $name.

A list of all universally available placeholders is available with a click on the placeholder button inside the toolbar of a multiline editor.

If custom placeholders are requried please contact our support team via ticket.

Example

$salutation_en_formal will be replaced with “Dear Mr. Doe,” if the recipient is male, or “Dear Ms. Doe,” if the recipient is female. If no gender is given, it will fall back to “Dear Sir or Madam,”

Conditions

It is also possible to personalize content with conditions.

Example

Personalized salutation with fallback
{!--<dynamicContent>
	<if>
		<condition>gender = 1 AND name != ""</condition>
		<data>Dear Mr $name,</data>
	</if>
	<elseif>
		<condition>gender = 2 AND name != ""</condition>
		<data>Dear Ms $name,</data>
	</elseif>
	<else>
		<data>Dear Sir or Madam,</data>
	</else>
</dynamicContent>//--}

Functions

pn_substr

With the function pn_substr is possible to shorten the value of placholders to a specified amount of characters.

E.g.: pn_substr(name, 10) shortens the name to 10 characters.

Config Tags

Config tags make it possible to control the behaviour of the email editor.

Attribute Type Default Description
cssinline boolean true Inline CSS from the \<style\> block.
cssinlinetype string default Set the type of the CSS inliner.
storage string (frame / shadow) frame Possible values: frame / shadow
ignoreerror boolean false Ignore errors on save.

Example

<pm:config>
    <pm:config-value name="cssinline" value="true"/>
    <pm:config-value name="cssinlinetype" value="ng"/>
    <pm:config-value name="storage" value="frame"/>
    <pm:config-value name="ignoreerror" value="true"/>
</pm:config>

Values for cssinlinetype

Value Description
default Use the legacy CSS inliner.
ng Use the new, improved CSS inliner.

The default CSS Inliner can only transform CSS for single, non-comma-separated selectors. The ng (“next generation”) CSS Inliner does not underlie those restrictions and can inline CSS blocks with comma-separated selectors.

Examples for the default CSS Inliner
<head>
<style>
	/*******************
	* Working examples * 
	*******************/
 
	.foo {
		font-size: 12px;
		line-height: 1.4;
	}
 
	.bar {
		background-color: #fff;
	}
 
	img {
		border: 0;
	}
 
 
	/***********************
	* Non-working examples * 
	************************/
 
	.baz, .boz {
		font-size: 15px;
	}
 
	table td {
		background-color: #ff0
	}
</style>
</head>
<body>
	/*******************
	* Working examples * 
	*******************/
	<table>
		<tr>
			<td class="bar">
				<span class="foo">Lorem ipsum dolor sit amet</span>
			</td>
		</tr>
		<tr>
			<img alt="" src="image.jpg" width="200" />
		</tr>
	</table>
 
 
	/***********************
	* Non-working examples * 
	************************/
	<table>
		<tr>
			<td class="foo bar">
				Lorem ipsum dolor sit amet
			</td>
		</tr>
	</table>
</body>

Values for storage

Value Description
frame Save the contents from the preview iframe. This will save changes made via the browser's development tools but is also susceptible to foreign code, e.g., made by browser plugins, which could destroy the presentability of the email.
shadow Save the contents from a shadow copy of the email. This assures that the email's source code could not be changed by browser plugins.
en/otml.txt · Zuletzt geändert: 2025/02/27 11:01 von bk