Welcome to TiddlyWiki created by Jeremy Ruston; Copyright © 2004-2007 Jeremy Ruston, Copyright © 2007-2011 UnaMesa Association
A/B split testing is a statistical mechanism for getting your audience to help you pick the best subject line and thus improve open rates. It applies only to open rates because message opening rate is unrelated to message content (because recipients only get to see message content //after// opening a message).
[IMG[images/absplit.gif]]
!The Process
# Create your mailshot as normal.
# In the subject tab, enable A/B split testing, write a second subject line and pick a delay time.
# Schedule your mailshot, bearing in mind that the delay time will affect delivery time for most of your recipients.
Everything else is taken care of for you and happens automatically.
!What Happens
A small portion of your mailing list is randomly selected and split into two halves. The first half receives the usual subject line, the second receives the alternative. These messages are sent as normal, and after they have been sent, your mailshot will be paused (it will be marked as "A/B split paused" on the mailings page). The duration of the pause is determined by the time you specified when creating the mailshot. During this time, your test recipients will have got their messages and treated them as usual: ignoring them, opening them, clicking in them. After the delay period has passed, we count the number of opens associated with each of the two subject lines; whichever one has generated the most opens is declared the winner, and the whole of the rest of the mailshot is sent using that subject line.
!Limitations of split testing
Because of the limits on the effectiveness of split testing (see below), we disable split test options for mailshots sent to lists below 5,000 subscribers, and results obtained from lists below 50,000 should be treated with suspicion! On smaller lists we are forced to use sub-optimal sample sizes – there's not much to be gained by making your entire mailshot a split test!
!The truth about split testing
A/B split testing is often paraded as a vital feature, however it's actually difficult to get meaningful results out of it. Assuming that you write two subject lines that are both as good as you think you can make them (there being no point in writing a deliberately bad one), chances are the difference in response will not be that big, perhaps only 2 or 3 percent. In order to detect that amount of difference, we need a sample size sufficiently large to distinguish a significant result from random variation. Applying statistical theory, to obtain a reading accurate to 2.5% with 95% certainty (the values we use for calculating sample size) in an unlimited population, we need 1,537 samples. Correcting for a finite list of say 20,000, we need 1,427.
Unfortunately that sample is the number of received responses, which corresponds to message openings, not messages sent. A decent list might get a 10% open rate (probably less given we have a limited time window), so we need to send more test messages in order to get the sample rate up to a meaningful level – in the case of our 20k list with a 10% open rate, we need around 14,000 test messages, which is 70% of the list, rendering the whole exercise mostly pointless!
The key thing to note is that the sample size does not increase much as the list size increases, so the bigger your list, the more effective and accurate split testing will be – it will only really start to become effective above around 50,000 subscribers, which renders it unsuitable for many small businesses who simply don't have that many subscribers.
!What about content splits and multivariate testing?
Many advocate taking split testing further, applying it to clicks and thus message content, however given a typical clickthrough rate of 3%, it fails to be statistically significant on lists below about 200,000 subscribers. If your lists are that big, great, but if not, split testing won't help you much. If you go further into multivariate testing, your sample sizes for significance spiral into impossibility. Multivariate testing is excellent and appropriate for web sites (which effectively have a 100% open rate), but it's just not very effective in email. That said, we're not here to stop you trying, so the A/B group selected for an individual message is available in the {{{$message.absplit}}} property, which you can use to create content switches in your message body or subject lines. See [[the template guide|TemplateGuide]] for more on how to do this.
While any split will usually result in a bias one way or another, below these sample sizes the results are not attributable to anything significant and are indistinguishable from random variation.
To experiment with the statistical values, have a play with [[this calculator|http://www.surveysystem.com/sscalc.htm]].
Our API provides access to various useful back-end functions in Smartmessages, in particular getting a list of mailing lists, subscribing and unsubscribing, and getting info on recipients (including mailing history).
Our API may be overkill for some tasks, particularly for simple synchronisation purposes – our [[Callback|Callbacks]] system may be all you need.
!!What's an API?
An API is an [[Application Programming Interface|http://en.wikipedia.org/wiki/Api]], and presents an access point through which you can write code to talk to Smartmessages behind-the-scenes functions without all that visual HTML stuff to get in the way. This might help you to:
* Build your own subscribe/unsubscribe pages
* Integrate with your CRM system
* Anything else you might want to do!
!!Implementation
The API is an [[RPC|http://en.wikipedia.org/wiki/Remote_Procedure_Call]]-style interface, expecting HTTP POST requests (with a few calls using GET) and providing responses suitable for direct consumption by ~Javascript ([[JSON|http://en.wikipedia.org/wiki/Json]]), PHP (serialised arrays), XML (everything else), plus simple HTML output to help you debug your code.
The initial focus of our API has been to make basic information available, and provide you with sufficient resources for you to build your own subscribe and unsubscribe pages. If you don't want to go that far, you can [[automate our subscribe and unsubscribe pages|Subscribing]] anyway. There are plenty more functions yet to come!
''Note that all string data, parameters and responses must use the ~UTF-8 character set''.
We reserve the right to withdraw API access, or to place restrictions on the quantity and/or rate of connections and requests.
!!How To Use The API
Firstly you'll need to get API access enabled for your login ID, or we can create a new login for you that has appropriate permissions. Next, go to your account tab inside Smartmessages and copy the API key shown below your account name. If you have access to multiple accounts, they will have different API keys. Then you need to start writing your scripts (using PHP, Java, ASP, Ruby, etc) that call the functions we provide.
!!!Give me the code!
We host our client libraries and example code [[on GitHub|https://github.com/Smartmessages]]. If you make some worthwhile changes, please fork our code on there and send us a pull request.
The quickest way to get started is using our [[PHP API wrapper classes|APIExamples]], which implements all features and is ready to go. If you're using another language, you might like to use that code as a basis. It's available via composer/packagist – just run {{{composer require smartmessages/phpclient}}} or add {{{smartmessages/phpclient}}} to the {{{require}}} section of your {{{composer.json}}} file. The library requires PHP 5.4 and the [[guzzle HTTP client library|https://github.com/guzzle/guzzle]] (and its own dependencies) so if you're not using composer you will need to add them manually.
The initial access point is {{{https://www.smartmessages.net/api/}}}, but when you log in, you will be provided with an endpoint URL that you should direct subsequent calls to. This allows us future flexibility in how we support the API. The PHP client class handles this for you.
Though we provide JSON output, it's not a good idea to implement access to this API using client-side ~Javascript, because it's not possible to do so without exposing your login credentials and API key, which would compromise the security of your data.
!!Errors and Feedback
Any function that fails for some reason will return a status value of false, usually accompanied by an error code, and a plain text error message. Some responses contain an additional message field for additional information about the function you just called.
!!!Defined error codes
* ~ERR_INCORRECT_ID_PASS: 1
* ~ERR_UNKNOWN_MISSING_METHOD: 2
* ~ERR_INCORRECT_METHOD_PARAMS: 3
* ~ERR_NO_PERMISSION: 4
* ~ERR_INVALID_EMAIL: 5
* ~ERR_USER_NOT_FOUND: 6
* ~ERR_ALREADY_SUBSCRIBED: 7
* ~ERR_SESSION_EXPIRED: 8
* ~ERR_MISSING_API_KEY: 9
* ~ERR_LOGIN_FAILED_SUSPENDED: 10
* ~ERR_LOGIN_STILL_SUSPENDED: 11
* ~ERR_INVALID_LIST_ID: 12
* ~ERR_SUBSCRIPTION_NOT_FOUND: 13
* ~ERR_INVALID_CUSTOMER_ID: 14
* ~ERR_LIST_UPLOAD_FAILED: 15
* ~ERR_LIST_NOT_YOURS: 16
* ~ERR_ACCOUNT_NOT_FOUND: 18
* ~ERR_NOT_YET_IMPLEMENTED: 19
* ~ERR_INVALID_URL: 20
* ~ERR_UNKNOWN_UPLOAD: 21
* ~ERR_INVALID_NAME: 22
* ~ERR_INVALID_CAMPAIGN_ID: 23
* ~ERR_CAMPAIGN_NOT_YOURS: 24
* ~ERR_TEMPLATE_NOT_FOUND: 25
* ~ERR_INCORRECT_API_KEY: 26
* ~ERR_TEMPLATE_NOT_YOURS: 27
* ~ERR_BAD_URL: 28
* ~ERR_DELETED: 29
* ~ERR_INVALID_MAILSHOT_ID: 30
* ~ERR_NEEDS_UPGRADE: 31
* ~ERR_INTERNAL: 99
Generally you should never receive an error 99 – please report it to us if you do.
!!Output formats
People like to work in different ways, so we provide output in multiple formats which you can choose as best fits your application by specifying which one you want when you log in:
*''php'': This is the result of serialising PHP variables, strings, arrays and objects. If you're working in PHP (as we are), this is by far the easiest format to deal with as all you need to do is [[unserialize($response)|http://www.php.net/manual/en/function.unserialize.php]] to have all the response data in a ready-to use format. This is the default format, and is also what our PHP client class uses.
*''json'': [[Javascript Object Notation|http://en.wikipedia.org/wiki/Json]] is an increasingly popular markup for web applications due to its compact syntax, ease of parsing and cross-language support.
*''xml'': XML is very popular and flexible, so we provide simple XML output too, though it's a bit more verbose and slower than json or php, so use them if you can.
*''html'': This outputs a simple full HTML page with a debug dump of the response on. This is only of use for debugging.
*''htmlfragment'': Outputs the same data as html format, but without html, head and body tags, useful for debugging if you're making several API calls.
!!Functions
Exact parameter names and response labels are given in //italic// text. Mandatory parameters are ''bold''. All functions except {{{login}}} require an //''accesskey''// parameter which you will receive in the response to a successful login call, and this parameter is not shown on parameter lists. All responses include an {{{expires}}} value which tells you when the current session will expire (as a standard UNIX timestamp); this allows you to check for expiry //before// you make an API call and thus avoid unnecessary error handling.
!!Connection functions
!!!login
!!!!Parameters:
*//''username''//: the email address that you use to log into Smartmessages
*//''password''//: your password
*//''apikey''//: the key you copied from your account tab.
*//outputformat//: an optional parameter to set the format to one of xml, json, php (the default), html or htmlfragment
!!!!Response
*//accesskey// => string 'abc123'
*//endpoint// => string 'https://www.smartmessages.net/api/'
*//status// => boolean true
*//accountname// => string 'Your account name'
*//username// => string 'Your login email address'
*//expires// => integer UNIX timestamp
This is the first function you need to call. You should check for the presence of the 'status' value and check that it is not false. You will also be provided with an access key which you will need for all subsequent function calls, and you should use the endpoint value to form the basis of your access ~URLs. The {{{expires}}} timestamp indicates when your session will expire, though it is extended every time you make a function call, and an updated value is provided in every response.
You need to provide your id and password as well as the API key because the API key is common to all users in an account, but permissions are defined per user.
So that you don't need to expose your own login credentials in source code you may provide to your own customers, we can create additional accounts that have ~API-only access that are unique for your application. Feel free to use your own ID while developing, and request a new separate ID from us when you're ready to deploy.
!!!ping
!!!!Parameters:
*None
!!!!Response:
*//status// => boolean
Does nothing except refresh your access key. Use this if you want to keep your access key valid for an extended period without actually doing anything.
!!!logout
!!!!Parameters:
*None
!!!!Response:
*//status// => boolean
Call this when you've finished using the API. After this call, your access key will no longer work, and you'll have to request a new one using {{{login}}}. If you don't call {{{logout}}}, your key will eventually expire anyway, but it helps us free up resources and thus keep Smartmessages performance high for everyone. The PHP client wrapper takes care of this for you.
!!Template functions
Note that all imported templates are subject to content filtering for security purposes. Generally this won't make any visible difference, but tags such as scripts and iframes will be removed, along with script-related attributes.
!!!gettemplates
!!!!Parameters:
*//includeglobal//: Boolean; whether to include the standard Smartmessages-supplied templates. Defaults to false.
*//includeinherited//: Boolean; whether to include templates inherited from parent accounts. Defauts to true.
!!!!Response
*//status// => boolean
*//templates// => array
Returns an array of all templates that you have access to.
!!!addtemplate
!!!!Parameters
*//''name''//: The name of the new template, max 100 characters.
*//''html''//: The HTML part of the template.
*//''plain''//: The plain-text half of the template.
*//''subject''//: The default subject line, max 100 characters.
*//description//: A description of the new template, max 255 characters.
*//generateplain// Boolean; whether to create a plain text version from the html version. Defauts to false. The ''plain'' parameter is ignored if this is set.
*//importimages// Boolean; Whether to import referenced images and rewrite ~URLs to point at the new locations on our servers.
*//convertformat// Boolean; Whether to detect and convert other template formats into Smartmessages format.
*//inline// Boolean; Whether to inline CSS when sending mailshots using this template.
!!!!Response
*//status// => boolean
*//templateid// => integer
*//importcount// => integer (The number of images imported, if any)
*//truncated// => boolean (Whether the template was truncated at the 200k limit).
Creates a new template. If images are set to import, they are placed in a folder based on the name of the template; any files with the same names will be overwritten. Images that fail to import are skipped and not reported, so it's a good idea to check the template afterwards. Image ~URLs with query strings are skipped (e.g. for third party tracking services).
!!!addtemplatefromurl
!!!!Parameters
*//''name''//: The name of the new template, max 100 characters.
*//''url''//: A URL of the web page you want to import.
*//''subject''//: The default subject line, max 100 characters.
*//description//: A description of the new template, max 255 characters.
*//importimages// Boolean; Whether to import referenced images and rewrite ~URLs to point at the new locations on our servers.
*//convertformat// Boolean; Whether to detect and convert other template formats into Smartmessages format.
*//inline// Boolean; Whether to inline CSS when sending mailshots using this template.
!!!!Response
*//status// => boolean
*//templateid// => integer
*//importcount// => integer (The number of images imported, if any)
*//truncated// => boolean (Whether the template was truncated at the 200k limit).
Creates a new template from a URL. This is useful if you develop or generate your templates on an external system. A plain-text version is created automatically. If images are set to import, they are placed in a folder based on the name of the template; any files with the same names will be overwritten. Images that fail to import are skipped and not reported, so it's a good idea to check the template afterwards. Image ~URLs with query strings are skipped (e.g. for third party tracking services).
If the URL fails to respond or returns an error, you'll get an {{{ERR_BAD_URL}}} error code. If you supply a malformed URL or one which doesn't use HTTP or HTTPS, you'll get an {{{ERR_INVALID_URL}}} error code.
!!!updatetemplate
!!!!Parameters
*//''templateid''// integer
*//''name''//: The new name of the template, max 100 characters.
*//''html''//: The HTML part of the template.
*//''plain''//: The plain-text half of the template.
*//''subject''//: The default subject line, max 100 characters.
*//description//: A description of the new template, max 255 characters.
*//generateplain// Boolean; whether to create a plain text version from the html version. Defauts to false. The ''plain'' parameter is ignored if this is set.
*//importimages// Boolean; Whether to import referenced images and rewrite ~URLs to point at the new locations on our servers.
*//convertformat// Boolean; Whether to detect and convert other template formats into Smartmessages format.
!!!!Response
*//status// => boolean
*//templateid// => integer
*//importcount// => integer (The number of images imported, if any)
*//truncated// => boolean (Whether the template was truncated at the 200k limit).
Creates a new template. Note you can only update templates that are in your account – not global or inherited ones. If images are set to import, they are placed in a folder based on the name of the template; any files with the same names will be overwritten. Images that fail to import are skipped and not reported, so it's a good idea to check the template afterwards. Image ~URLs with query strings are skipped (e.g. for third party tracking services).
!!!deletetemplate
!!!!Parameters
*//''templateid''// integer
!!!!Response
*//status// => boolean
Deletes a template. Note you can only delete templates that are in your account – not global or inherited ones.
''Warning: also deletes any mailshots that used this template''.
!!Campaign functions
Campaigns are groups of mailshots organised into folders – don't get them confused with mailshots.
!!!getcampaigns
!!!!Parameters:
*None
!!!!Response
*//status// => boolean
*//campaigns// => array
Returns a list of all campaign ids and names in your account.
!!!addcampaign
!!!!Parameters
*//''name''//: The name of the new campaign, max 100 characters.
!!!!Response
*//status// => boolean
*//campaignid// => integer
Creates a new campaign folder into which you can put new mailshots, or move existing mailshots.
!!!updatecampaign
!!!!Parameters
*//''campaignid''// => integer
*//''name''//: The new name for the campaign, max 100 characters.
!!!!Response
*//status// => boolean
Changes the name of an existing campaign. Note that campaign names don't have to be unique, though it's in your own interests to make them so!
!!!deletecampaign
!!!!Parameters
*//''campaignid''// => integer
!!!!Response
*//status// => boolean
Deletes a campaign.
''Warning: also deletes any mailshots contained in the campaign''.
!!!getcampaignmailshots
!!!!Parameters
*//''campaignid''// => integer
!!!!Response
*//status// => boolean
*//mailshots// => array
Returns an array of useful information about all the mailshots contained by a campaign.
!!Mailshot functions
See also getcampaignmailshots
!!!getmailshot
!!!!Parameters:
*//''mailshotid''//: The integer id of the mailshot you want
!!!!Response:
*//status// => boolean
*//mailshot// => array
**//name// => string
**//subject// => string
**//mailinglistid// => integer The id of the mailing list this mailshot is to
**//templateid// => integer The id of the template being sent
**//campaignid// => integer The id of the campaign this mailshot is stored in
**//status// => string 'unsent', 'complete', 'sending', 'error' etc
**//date_sent// => an ~ISO-8601 date in '~YYYY-MM-DD HH:MM:SS', or a zero date if it's unsent, of the time the mailshot was sent
**//from_address// => string The email address the message is sent from
**//from_name// => string The name the message is sent from
**//replyto// => string The email address replies go to, if different from the from address
**//date_completed// => an ~ISO-8601 date in '~YYYY-MM-DD HH:MM:SS', or a zero date if it's unsent or incomplete, of the time the mailshot completed
**//thumbnail_url// => string A URL of an image of the mailshot as sent (scaled to fit in a 320x320 pixel box)
**//preview_url// => string A URL of a web version of the mailshot as sent
**//recordcount// => integer number of subscribers in the uploaded list (not populated until upload complete)
**//messagecount// => integer Number of messages in this mailshot
**//opencount// => integer number of openings recorded
**//clickcount// => integer number of clicks recorded
Gets information about an existing mailshot.
!!!sendmailshot
!!!!Parameters
*//''templateid''//: The id of the template to send.
*//''listid''//: The id of the mailing list to send to.
*//title//: The title of the new mailshot, max 100 characters. If omitted, will generate a name based on the date.
*//campaignid//: The id of the campaign to put the mailshot in. if omitted, will use your test campaign.
*//subject//: The subject template to use (allowed syntax is the same as for templates). Will use the template's default subject if omitted.
*//fromaddr//: The email address to use as the from address (should be in a domain you have set up DKIM and SPF for). If omitted, will use your accoutn default, or your login address.
*//fromname//: The name to use as the sender. Defaults to your account default.
*//replyto//: An address that replies should go to, if different to the from address.
*//when//: When to send the mailshot. Either the word 'now' (the default), or an ~ISO-8601 date in '~YYYY-MM-DD HH:MM:SS' format.
!!!!Response
*//status// => boolean
*//mailshotid// => integer
Creates a new mailshot and schedules it for sending.
!!!getmailshotclicks
!!!!Parameters:
*//''mailshotid''//: The integer id of the mailshot you want
*//ascsv//: Boolean. Whether to return the result in CSV format
!!!!Response:
*//status// => boolean
*//clicks// => array
**//url// => string The link they clicked on
**//email// => string The address of the recipient that clicked
**//timestamp// => an ~ISO-8601 UTC date in '~YYYY-MM-DD HH:MM:SS'
Gets a list of clicks relating to a particular mailshot. If the {{{ascsv}}} parameter is supplied and true, results will be provided in CSV format, which is smaller, faster and easier to handle (just save it directly to a file) than other formats.
!!!getmailshotopens
!!!!Parameters:
*//''mailshotid''//: The integer id of the mailshot you want
*//ascsv//: Boolean. Whether to return the result in CSV format
!!!!Response:
*//status// => boolean
*//opens// => array
**//email// => string The address of the recipient that clicked
**//timestamp// => an ~ISO-8601 UTC date in '~YYYY-MM-DD HH:MM:SS'
Gets a list of opens relating to a particular mailshot. If the {{{ascsv}}} parameter is supplied and true, results will be provided in CSV format, which is smaller, faster and easier to handle (just save it directly to a file) than other formats.
//Note that we record a single extra open event for recipients that click if they do not have an open logged already. This allows us to avoid the nonsensical situation where someone has apparently clicked whithout opening, which could lead to unique clicks being larger than unique opens.//
!!!getmailshotunsubs
!!!!Parameters:
*//''mailshotid''//: The integer id of the mailshot you want
*//ascsv//: Boolean. Whether to return the result in CSV format
!!!!Response:
*//status// => boolean
*//unsubs// => array
**//email// => string The address of the recipient that clicked
Gets a list of unsubscribes relating to a particular mailshot. If the {{{ascsv}}} parameter is supplied and true, results will be provided in CSV format, which is smaller, faster and easier to handle (just save it directly to a file) than other formats.
!!!getmailshotbounces
!!!!Parameters:
*//''mailshotid''//: The integer id of the mailshot you want
*//''ascsv''//: Boolean. Whether to return the result in CSV format
!!!!Response:
*//status// => boolean
*//bounces// => array
**//email// => string The address of the recipient that clicked
**//code// => integer The bounce reason code
**//type// => string Hard, soft or other
**//reason// => string Text description of the bounce, for example 'Soft bounce – Mailbox full'
**//timestamp// => an ~ISO-8601 UTC date in '~YYYY-MM-DD HH:MM:SS'
Gets a list of bounces relating to a particular mailshot. This is the same information as is downloadable from the contacts page, except that this is for a single mailshot, not a whole list (which might cover multiple mailshots). If the {{{ascsv}}} parameter is supplied and true, results will be provided in CSV format, which is smaller, faster and easier to handle (just save it directly to a file) than other formats.
!!List functions
!!!addlist
!!!!Parameters
*//''name''//: The name of the new list, max 100 characters.
*//description//: A description of the new list, max 255 characters.
*//visible//: Boolean. Whether the new list should be publicly visible, defaults to true.
!!!!Response
*//status// => boolean
*//listidid// => integer
Creates a new mailing list, ready for you to upload subscribers into. List names do not have to be unique.
!!!updatelist
!!!!Parameters
*//''listid''// => integer
*//''name''//: The new name for the list, max 100 characters.
*//''description''//: The new description for the list, max 255 characters.
*//''visible''//: Boolean. Whether the list should be publicly visible
!!!!Response
*//status// => boolean
Changes the properties of an existing list. Note that all parameters are mandatory.
!!!deletelist
!!!!Parameters
*//''listidid''// => integer
!!!!Response
*//status// => boolean
Deletes a list.
''Warning: also deletes any mailshots that have used this list''.
!!!getlists
!!!!Parameters:
*//showall//: (optional) Whether to include all mailing lists, or just those set to 'visible' (the default). 1 for true, 0 for false.
!!!!Response (example data):
*//status// => boolean
*//mailinglists// => array
**341897 => array
***//id// => int 341897
***//name// => string 'Announcements'
***//description// => string 'Occasional information releases'
***//visible// => boolean true
**341886 = array
***//id// => int 341886
***//name// => string 'Newsletter'
***//description// => string 'Regular monthly news, hints & tips'
***//visible// => boolean true
This function returns a list of all the mailing lists that are available in your account that are set to be visible (editable on each mailing list page). The response contains the list ID, its name, and a description of each list, and the array of lists is also indexed by the list ID. Normally the list returned only includes lists that are set to visible, i.e. those that appear on the default landing page; If you add the 'showall' boolean parameter ad set it to 1, the response will include all lists, not just those that are marked as visible. The response includes a 'visible' property for each list which you can use to decide whether to display the list in your own pages.
!!!getlist
!!!!Parameters:
*//''listid''//: The integer id of the list you want
*//ascsv//: Boolean. Whether to return the result in CSV format
!!!!Response:
*//status// => boolean
*//list// => array
** Each entry is a large structure similar to what is returned by //''getuserinfo''//.
Gets a complete list of recipients on a mailing list. If the {{{ascsv}}} parameter is supplied and true, results will be provided in CSV format, which is smaller, faster and easier to handle (just save it directly to a file) than other formats.
''We //strongly// recommend that you use the {{{ascsv}}} option with this function as the response can be extremely large in PHP, JSON or XML formats, extending to hundreds of megabytes for large lists, taking a correspondingly long time to download, and possibly causing memory problems in client code. For this reason, this function defaults to CSV format.''
!!!gettestlist
!!!!Parameters
* //none//
!!!!Response
*//status// => boolean
*//id// => integer
*//name// => string
*//description// => string
Fetches the details of your designated test list. If you do not have a designated test list, one will be created for you. Mailshots to your test list are sent immediately and with higher priority than regular mailshots, but are limited to 16 subscribers.
!!!getlistunsubs
!!!!Parameters
*//''listid''//: The id of the list you want to get unsubscibes from (obtained using the getlists function)
!!!!Response (example data):
*//status// => boolean
*//unsubscribes// => array
**string 'user1@example.com'
**string 'user2@example.com'
**string 'user3@example.com'
Provides a list of all addresses that have unsubscribed from the given list. Note that unsubscribes are retained even if the list is empty, and used to suppress unsubscribed addresses from subsequent uploads. We suggest you occasionally download unsubscribes in order to update your own copies of mailing lists (or make use of our callbacks in order to retain real-time sync).
!!List upload functions
!!!uploadlist
!!!!Parameters:
*//''listid''//: The integer id of the list you want to upload into (obtained using the getlists function)
*//''source''//: A short string describing where this list came from, for example if it's a bought list, the supplier name and order reference. This is used to retain audit trails of your subscribers.
*//definitive//: A boolean value indicating whether this upload is to be considered definitive data that should overwrite any existing data you have for each recipient for the included fields. See MailingLists for more info on the behaviour behind this. Defaults to false.
*//replace//: A boolean value indicating whether anyone already on this list that is not in this new upload should be removed. The default behaviour is to add to the list (i.e. false).
*//firstlinefields//: A boolean value indicating whether the first line of the file contains field names (note that these must match allowed field names). Defaults to false.
*//''file''//: The list file
!!!!Response:
*//status// => boolean
*//uploadid// => integer
This is a complex function used for uploading entire mailing lists in one go. It differs from the rest of our ~APIs in that it requires that your HTTP POST contains a {{{multipart/form-data}}} MIME body. Our reference PHP implementation does this for you and may provide a good basis for you to write code in other languages.
Currently the list file must be in standard [[RFC4180|http://www.rfc-editor.org/rfc/rfc4180.txt]] CSV format – comma-delimited, optional double-quote delimiter escaping, double quotes escaped by themselves. This format can be exported from programs like Excel, Filemaker, Access, ~QuickBooks and numerous CRM packages.
The uploading process is asynchronous – this function will return when the physical file transfer is complete, but the actual import of the data takes longer, so you need to monitor its progress and do not send mailshots to the new list until it is complete. This function returns an integer identifier that can be used to query the status of an upload using the {{{getuploadinfo}}} call. You may only submit a single list file per request, and it can be compressed as a zip archive (in which case only the first file inside the archive will be used). There is a limit of 50Mb (uncompressed size).
In the absence of field names in the upload, the importer will fall back to whatever the field list is set to for the account, and if that is not set, to our default field order. The account field order can be set on the settings page, or though the API call {{{setimportfields}}}.
!!!getuploads
!!!!Parameters:
*//''listid''//: The integer id of the list you want upload info for (obtained using the getlists function)
!!!!Response:
*//status// => boolean
*//uploads// => array
**0 => array
***//id// => integer the upload ID
***//status// => string 'pending', 'in progress', 'cancelled', 'complete', 'error' etc
***//progress// => integer (percentage)
***//cancelled// => boolean false (whether the upload has been cancelled)
***//filename// => string 'mylist.csv'
***//recordcount// => integer number of subscribers in the uploaded list (not populated until upload complete)
***//badcount// => integer number of invalid addresses in the uploaded list (not populated until upload complete)
***//groupcount// => integer number of addresses that look like group addresses in the uploaded list (not populated until upload complete)
***//uploaddate// => date and time (~ISO-8601 format) the upload completed (not populated until upload complete)
This function gets a history of all uploads, including recent ones. Typically you should call this function when monitoring an upload's progress in preference to the getuploadinfo function as it's faster and returns less information that's not relevant to the upload progress (even though it returns info on more than one upload).
!!!getuploadinfo
!!!!Parameters:
*//''listid''//: The integer id of the list you want upload info for (obtained using the getlists function)
*//''uploadid''//: The integer id of the particular upload you want info for (obtained using the getuploads or uploadlist functions)
!!!!Response:
*//status// => boolean
*//upload// => array
**//id// => integer The upload ID
**//status// => string 'pending', 'in progress', 'cancelled', 'complete', 'error' etc
**//progress// => integer (percentage)
**//cancelled// => boolean false (whether the upload has been cancelled)
**//filename// => string 'mylist.txt'
**//recordcount// => integer number of subscribers in the uploaded list (not populated until upload complete)
**//badcount// => integer number of invalid addresses in the uploaded list (not populated until upload complete)
**//groupcount// => integer number of addresses that look like group addresses in the uploaded list (not populated until upload complete)
**//uploaddate// => date and time (~ISO-8601 format) the upload completed (not populated until upload complete)
**//badaddresses// => array The array of invalid email addresses, if any.
*** 0 => 'invalid@example.'
**//groupaddresses// => array The array of group email addresses, if any.
*** 0 => 'sales@example.com'
*** 1 => 'customerservices@example.com'
**//definitive// => boolean true (whether the upload was uploaded in definitive mode – see the uploadlist function)
**//replace// => boolean true (whether the upload was uploaded in replace mode – see the uploadlist function)
**//firstlinefields// => boolean true (whether the upload had field names in its first line – see the uploadlist function)
**//contactcount// => integer number of entirely new contacts in this list (not populated until upload complete)
**//subcount// => integer number of new subscriptions in this list (not populated until upload complete)
**//suppressunsubcount// => integer number of unsubscribes suppressed from this upload (not populated until upload complete)
**//suppressspamcount// => integer number of spam reporters suppressed from this upload (not populated until upload complete)
**//suppressbouncecount// => integer number of known bouncing addresses suppressed from this upload (not populated until upload complete)
**//uploadbyid//: integer The ID of the user that did the upload – can be fed into the getuserinfo function
**//source//: A short string describing where this list came from, see uploadlist for details
!!!cancelupload
!!!!Parameters:
*//''listid''//: The integer id of the list the upload is in (obtained using the getlists function)
*//''uploadid''//: The integer id of the particular upload you want to cancel (obtained using the getuploads or uploadlist functions)
!!!!Response:
*//status// => boolean
If an upload has 'pending' or 'in progress' status, it can be cancelled, and none of the addresses on it will appear on the list and none of the field data changed by it will be applied.
!!Subscriber functions
!!!subscribe
!!!!Parameters
*//''address''//: The email address you want to subscribe
*//''listid''//: The id of the list you want to subscribe to (obtained using the getlists function)
*//name//: Optionally, the name you want to give to this subscriber. Goes into the 'Dear' field within Smartmessages, usually used when addressing the recipient, e.g. 'John', 'Dr Who', 'Mr President', 'Gnasher' etc.
*//title//: Optionally, the title name you want to give to this subscriber.
*//firstname//: Optionally, the subscriber's first name.
*//lastname//: Optionally, the subscriber's last name (surname).
*//companyname//: Optionally, the subscriber's company name.
*//allow_tracking//: Optionally, whether the subscriber has given explicit consent for tracking (boolean).
!!!!Response:
*//status// => boolean
*//msg// => string optional message
Doesn't need much explanation! If your subscription policy is confirmed or double opt-in (which it is by default), your recipients will receive a confirmation message which they may need to respond to before they receive messages from this list. If you subscribe someone who is already on the list, you will not get an error, but you will receive an additional //msg// property in the response saying so. The optional naming fields provide an easy way to add someone to a list and record their name in one go without having to call setuserinfo later, so it's ideal as something to work behind a signup form on your web site.
!!!addsubscription
!!!!Parameters
*//''address''//: The existing subscriber's email address you want to add to another list
*//''listid''//: The id of the list you want to add them to (obtained using the getlists function)
*//note//: An optional description of why this subscription was added, limit of 100 chars.
!!!!Response:
*//status// => boolean
{{{addsubscription}}} is similar to {{{subscribe}}} but without the associated semantics – it simply adds an ''existing'' subscriber to the list. It may only be applied to existing subscribers that are already subscribed to one or more of your lists and so do not require additional opt-in permission. This is useful for administrative changes, for example adding a known, existing subscriber to a new list in response to a form submission, and the {{{note}}} parameter assists in auditing why this happened. Note that new subscribers ''will'' be sent messages if the target list has an active [[continuous mailshot|Continuous mailshots]] associated with it.
!!!unsubscribe
!!!!Parameters
*//''address''//: The email address you want to unsubscribe
*//''listid''//: The id of the list you want to unsubscribe from (obtained using the getlists or getuserinfo functions)
!!!!Response
*//status// => boolean
If you try to unsubscribe someone from a list that is not on it, you will receive an error response. Unsubscribes take effect immediately.
!!!deletesubscription
!!!!Parameters
*//''address''//: The email address you want to delete from a list
*//''listid''//: The id of the list you want to delete the subscriber from (obtained using the getlists or getuserinfo functions)
!!!!Response
*//status// => boolean
This works just like the unsubscribe call but without the associated semantics, so there will be no unsubscribe notification, no global unsubscribe action, no addition to suppressions etc, the subscriber is simply removed from the specified list with no other side-effects.
If you try to delete someone from a list that is not on it, you will receive an error response. Deletes take effect immediately.
!!!getuserinfo
!!!!Parameters
*//''address''//: The email address you want to get info on.
!!!!Response (example data):
*//status// => boolean {{{true}}}
*//userinfo// => array
**//email// => string 'user@example.com'
**//ownerdata// => string 'abc123'
**//title// => string 'Mr'
**//initials// => string 'FJ'
**//jobtitle// => string 'Marketing Director'
**//firstname// => string 'Finbar'
**//lastname// => string 'Jones'
**//dear// => string 'Mr Jones'
**//companyname// => string 'Example Marketing'
**//address1// => string 'Example House'
**//address2// => string 'Noodle Road'
**//address3// => string
**//county// => string
**//posttown// => string 'London'
**//postcode// => string '~SE1 5OK'
**//country// => string 'GB'
**//phone// => string '020 8123456'
**//fax// => string
**//mobile// => string
**//dob// => string '1971-05-27'
**//url// => string 'http://www.example.com/'
**//timezone// => string 'Europe/London'
**//custom1// => string 'custom value 1'
**//custom2// => string 'custom value 2'
**...
**//custom31// => string 'custom value 31'
**//custom32// => string 'custom value 32'
**//allow_tracking// => boolean {{{false}}}
**//subscriptions// => array
***0 => array
****//listid// => int 341897
****//name// => string 'Announcements'
****//description// => string 'Occasional information releases'
****//visible// => boolean true
***1 => array
****//listid// => int 341886
****//name// => string 'Newsletter'
****//description// => string 'Regular monthly news, hints & tips'
****//visible// => boolean true
***2 => array
****//listid// => int 341889
****//name// => string 'Test list'
****//description// => string
****//visible// => boolean false
**//mailshots// => array
***0 => array
****//mailshotid// => int 33988
****//name// => string 'First test'
****//date_sent// => string '2007-07-06 14:20:00'
****//listid// => int 341889
****//previewurl// => string 'http://www.smartmessages.net/web/3939_33988_'
***1 => array
****//mailshotid// => int 33989
****//name// => string 'Example July Newsletter'
****//date_sent// => string '2007-07-06 15:20:24'
****//listid// => int 341886
****//previewurl// => string 'http://www.smartmessages.net/web/3939_33989_'
This returns lots of useful information about the recipient. You can see all their personal data, their current subscriptions (including those to invisible lists), and a list of all the messages they have been sent (along with preview ~URLs so you can see a message like the one they were sent). The list of personal data fields is subject to change, but we'll try to only add fields rather than take them away.
!!!setuserinfo
!!!!Parameters
*//''address''//: The email address you want to get info on.
*//''userinfo''//: An array of properties to set
!!!!Response:
*//status// => boolean
Provides a counterpart to the getuserinfo function for setting personal data, perhaps to sync with your CRM system, or provide storage back-end for a custom form. A user's properties have the same names as those returned from getuserinfo, but you need to wrap them in an HTML array style query string – there is a function in the [[example code|APIExamples]] to do that for you. Note that you CANNOT change a user's email address. If you need to change an email address, unsubscribe the current address and re-subscribe under the new address.
Some fields have input constraints:
*Only ~UTF-8 encoding is supported
*Most address fields are limited to 100 characters
*Phone numbers are limited to 20 characters
*Dates must be in ~ISO-8601 ~YYYY-MM-DD format
*Country requires a 2-character ~ISO-3166 code (Notably the UK is {{{GB}}} in this scheme)
*Only custom fields are allowed to contain line breaks
*Custom fields are limited to 255 characters
Fields that are not set are not changed, fields that are set but empty will be cleared.
The meaning of custom fields is entirely up to you, and you are limited to 32 custom fields.
!!Account-level functions
!!!getspamreporters
!!!!Parameters
*None
!!!!Response (example data):
*//status// => boolean
*//spamreporters// => array
**string 'user1@example.com'
**string 'user2@example.com'
**string 'user3@example.com'
Provides a list of addresses that have reported emails from you as spam, at ~ISPs that we receive such reports from. Note that these are treated account-wide – users are unsubscribed from all your lists and prevented form being added to any list in future – it's just not worth trying to retain such recipients.
!!!getcallbackurl
!!!!Parameters:
*None
!!!!Response:
*//status// => boolean
*//url// => text
Retrieve the callback URL for your account.
!!!setcallbackurl
!!!!Parameters:
*//''url''//: text ~'http://www.example.com/callback.php' (put your callback URL here)
!!!!Response:
*//status// => boolean
Set the callback URL for your account. This must be a complete, valid URL using either HTTP or HTTPS protocol. Setting the URL to an empty string will disable callbacks; If callbacks have been disabled on your account (e.g. if your callback handler breaks), setting the URL to a valid, non-empty value (including to its existing value) will re-enable callbacks. If the URL you provide is invalid, the existing value will not be changed.
!!Utility functions
!!!validateaddress
!!!!Parameters:
*//''address''//: string email address
!!!!Response:
*//status// => boolean
*//valid// => boolean
A utility function to assess whether an email address is valid. This is the same check as we use internally to spot bad addresses during uploads. Just submit an address and check the value of the 'valid' response property. [[Read more|Email Address Validation]] about address validation.
The easiest way to get up and running with our [[API]] is to use a client library for your language. If you run into problems or have improvements to any of these, please open requests on their respective bug trackers. If you have any ideas or improvements you'd like to see in our API, please contact us.
!!PHP
We provide a client wrapper class and sample code for our API in PHP which you can find [[on GitHub|https://github.com/Smartmessages/PHPClient]]. You will need to substitute your own login ID, password and API key in the example script. This is also available via packagist/composer as {{{smartmessages/phpclient}}}.
!!ASPX
We also have an [[ASPX.NET|https://github.com/Smartmessages/ASPXClient]] library that was contributed by a Smartmessages customer. We are not ASPX experts, so any improvements you make to this would be very welcome!
You can send as many messages as your [[prepaid credits|Payment]] will cover. There are no other limits.
Smartmessages previously operated on a contact count limit rather than a message limit, but that is no longer the case.
Under the ''Settings'' tab you can:
Change your password & manage your time zone
[IMG[images/personal.gif]]
Edit your company details:
[IMG[images/account.gif]]
Attach in Google Analytics:
[IMG[images/google.gif]]
Set up your domain authentication to get better delivery:
[IMG[images/domain.gif]]
Set up your field order so that uploads are in your own format:
[IMG[images/fieldorder.gif]]
Smartmessages does not have auto-responders as they are more appropriately handled by CRM systems.
You can achieve some of the functionality that autoresponders are commonly used for using [[Continuous mailshots]].
There are several ways that you can automate interactions with Smartmessages:
*Calling our standard [[subscribe|Subscribing]] and [[unsubscribe|Unsubscribes]] forms
*Using our [[API]]
*Using [[callbacks|Callbacks]]
*Using [[Continuous mailshots]]
Please read those sections for more details
A bounce or bounceback is a message received from a mail server describing a failed delivery attempt. A typical example would be if you sent jack@example.com an email, but there's nobody called jack at example.com, so the mail server at example.com sends a message back to a special address we put in each message describing why the message couldn't be delivered. We handle all the bounces that your mailings generate, analyse them, take necessary action, and provide reports on them.
Bounces are a thorny problem for any mailing list system. Mail servers are unpredictable and very often badly configured, and you're likely to interact with several thousand different ones on a reasonable size mailing.
People often talk of 'hard' and 'soft' bounces without really knowing what they mean. In fact, hard bounces are the only ones of any real interest, and even then they are not necessarily 'hard' at all – it's all much less black and white that you might have been led to believe. Generally a hard bounce is one that is negative and likely to be permanently true, for example a reply which says 'this user does not exist'. A soft bounce is pretty much anything else, even those that describe themselves as 'permanent', 'fatal' or other such strong terms – for example a user's mailbox being full is classed as a permanent error, even though they could empty it at any moment.
When we receive a bounce message, we try to interpret what it says as accurately as possible, but it's not easy. Though there are some common standards for such messages, adherence to the rules is pretty bad. Our mail servers use a bounce processing system based on [[BoogieTools BounceStudio|http://www.boogietools.com/]]. We return the same codes we receive from their handling of bounces in the downloadable bounce reports we provide. Here's an overview of the codes:
|!Bounce Type|!Description|
|0|NON BOUNCE|
|10|HARD BOUNCE|
|20|SOFT BOUNCE – General|
|21|SOFT BOUNCE – Dns Failure|
|22|SOFT BOUNCE – Mailbox Full|
|23|SOFT BOUNCE – Message Size Too Large|
|30|BOUNCE WITH NO EMAIL ADDRESS|
|40|GENERAL BOUNCE|
|50|MAIL BLOCK – General|
|51|MAIL BLOCK – Known Spammer|
|52|MAIL BLOCK – Spam Detected|
|53|MAIL BLOCK – Attachment Detected|
|54|MAIL BLOCK – Relay Denied|
|60|AUTO REPLY|
|70|TRANSIENT BOUNCE|
|80|SUBSCRIBE REQUEST|
|90|UNSUBSCRIBE REQUEST|
|100|CHALLENGE RESPONSE|
Most of these broad categories are easy enough to understand. A non-bounce is a message that's ended up at our bounce return address that isn't a bounce, for example if a recipient sent a reply to the bounce address instead of from or replyto addresses because their mail program was misconfigured, or because a spam generator guessed lucky and created a legitimate bounce address for a spam message. For full details on what these codes mean, [[read their documentation|http://www.boogietools.com/Products/Linux/BounceStudioAPI/help/files/BounceTypes.html]].
Bounces can take time – so just because your mailshot has all been sent and you have a nice low bounce count, don't be surprised when you find that it increases later on. We've had some mail servers send us bounces 6 months after sending!
We use [[VERP|http://en.wikipedia.org/wiki/Variable_envelope_return_path]] addressing for our return path (where bounces go), so we can cope with some server misconfigurations – for example, Microsoft Exchange sometimes sends bounces that don't actually say who the original message was sent to (helpful, huh?!), but because of our addressing system, we can still figure out who it was.
Sometimes we get a bounce that says 'Uh, something didn't work' with no indication of what or why it failed, and though we try, there's not a lot we can do about such messages – it may be that the user doesn't exist, or their mailbox is full, or their mail server is just rubbish (it happens!). Sometimes mail servers just go nuts – we once had a major ISP's mail server send us 30,000 bounce messages in reply to a single message! There's only so much we can do – and all mailing list providers are in the same boat here.
!!!Greylisting
Some mail servers use [[greylisting|http://en.wikipedia.org/wiki/Greylisting]] in an often successful attempt to fool the millions of zombie ~PCs responsible for most spam into not sending them messages. This involves initially rejecting an incoming message, but allowing it to be received later on. It relies on the idea that the minimal mail senders in such programs will never get around to trying again and don't care if some of their millions of messages are not delivered. Because we run well-behaved mail servers, we have full support for this system – but be aware that it can mean that messages take longer to be delivered.
!!Automatic unsubscribe of bounces
We automatically unsubscribe consistently bouncing addresses after approximately three bounces. It's approximate because we adapt according to the historical behaviour of each address, for example if a hard bounce happens in a sequence of otherwise successful deliveries to an address, it will be ignored and future deiveries won't be affected. There is a major exception to this: Yahoo! domains (and other domains they handle, such as btinternet.com) are unsubscribed after a single hard bounce; it's a requirement of their terms of service for deliveries, and repeatedly attempting deliveries to their domains just results in delivery penalties.
Because these bounces are not dependent on content or source, we maintain them globally, so that if an address is bouncing for one of our other customers, it will be suppressed from your lists when you upload them, which helps improve your deliverability by not sending to known-bad addresses – //even on your very first send//!
We auto-unsubscribe bounces that are reported as 'unknown user', 'unknown domain', 'mailbox full' or 'bad address syntax'. It's useful to remove 'mailbox full' addresses as these days mailboxes are rarely full for real users, so they are likely to be defunct accounts that are accumulating junk, especially if they give that error consistently over several delivery attempts.
Smartmessages can display your branding in place of ours on several pages your subscribers may visit. The options controlling this are on the branding tab, which you'll find under the account tab.
If you set these options, we will use your branding on the following pages:
* Your landing page
* All subscribe pages
* All unsubscribe pages
* Double-opt-in verification page
* Your privacy policy page
* Branding test page
* Subscriber options pages (shown to subscribers when taking up their right to access their own data)
!Account logo
We can make use of your own logo in numerous places around our web site and in some email messages. Create a logo image with the following criteria:
* Must fit into 256 pixels wide by 128 pixels tall.
* Images bigger than this will be scaled down to fit.
* Images smaller than this will ''not'' be scaled up.
* Be in PNG format (other formats will be converted into PNG, so you can upload other formats if you like).
* PNG transparency will be preserved (and is highly recommended).
* Must be readable on a light background – white text on a transparent background will be invisible if we display it on a white page.
Here's an example; our own logo:
[IMG[https://www.smartmessages.net/logo/2]]
Your logo will be used in the following locations:
* In the header of all notification messages sent to your subscribers
* On the home page.
* On the home page of accounts that you refer to us.
* In any email templates that you place the {{{[[$account.logo]]}}} tag in.
We may add to this list in future.
!Fonts and colours
The most straightforward branding option is to use the colour pickers and font stack boxes on the branding page. These are integrated into a simple style sheet on each branded page or email. Either use the colour pickers to select foreground or background colours, or paste in your own HTML colour values (hex strings like {{{#ff5533}}}).
[IMG[images/fonts.gif]]
We recommend that the colours you pick must meet the 4.5:1 minimum relative contrast ratio as given in the [[WCAG 2.0 web accessibility standards|http://www.w3.org/TR/UNDERSTANDING-WCAG20/visual-audio-contrast-contrast.html]].
As well as being available in your public web pages and standard emails, the fonts and colours are also used in our notification emails.
Fonts are specified as a CSS font stack, which is a list of font names from most to least specific. There are many popular fonts to choose from, but we don't support loading custom web fonts,so you should limit you choices to standard web fonts. A typical font stack might be:
{{{
"Helvetica Neue", Helvetica, Arial, sans-serif
}}}
In this example, Helvetica Neue is typically available on iOS, Helvetica on Mac and some Windows systems (in that order), Arial is available on almost all Windows systems and some Mac, and sans-serif is a generic sans-serif font, which may in fact resolve to Helvetica or Arial anyway. Web browsers will pick the first one in the list that is available to them, so it's imporant to order them from least to most common. There are many other possible font stacks; look at sites like [[this one|http://cssfontstack.com/]] to help you pick one to match your branding.
You can set two font stacks – a heading stack for all levels of HTML headings ({{{h1}}}, {{{h2}}} etc), and a body stack that's used for everything else.
These font stacks and colours are also available as tags to use in your templates.
!Page headers, footers and styles
The boxes allow you to supply HTML snippets for a header and footer that will be placed before and after the main page content, and a CSS style sheet that will allow you to override [[our standard style sheet|https://www.smartmessages.net/css/smartmessages.css]], so you can change fonts, set page width, set backgrounds etc. Here are simple examples of each:
!!Header
{{{
<div id="header" style="background-color: purple; width: 100%; height:100px;text-align: center;"><img alt="Smartmessages header logo" height="63" src="https://smartmessages.smm.im/eheader.gif" style="border: 0px;" width="600"></div>
}}}
!!Footer
{{{
<div id="footer" style="background-color: green; width: 100%; height:100px;text-align: center;"><img alt="email header" height="63" src="https://smartmessages.smm.im/eheader.gif" style="border: 0px;" width="600"></div>
}}}
!!Style Sheet
{{{
.container-fluid {
width: 960px;
margin: 0 auto;
}
}}}
While this example uses a fixed width, we recommend that you design header and footer with full-width layouts in mind; that way your styles will work correctly with our responsive layouts when viewed on mobile platforms, where fixed widths generally don't work well. Also be sure to use the {{{header}}} and {{{footer}}} id attributes so that styles can target headers and footers correctly.
The style sheet you set here is loaded ''before'' the styles set when using the colour and font settings above, so if you want to set your fonts and colours in your style sheet, make sure you clear all the font and colour settings.
If you refer to images that are not served over HTTPS (TLS) your users will receive security notices in Internet Explorer, so either upload your graphics through our files area and serve them securely from our ~URLs, or host them yourself on a secure server.
!Notification messages
We are often asked about branding of notifications that are sent when users subscribe and unsubscribe. These messages serve a specific technical role, and they absolutely have to remain working and contain some specific text in order for us to conform to the necessary legal requirements – allowing them to be edited is extremely likely to compromise that role and thus make both you and us liable for the consequences, so we don't allow it in general. That said, we do make use of a logo as described above, and also the colour and font options. If you set these options, our own branding is limited to a mention in the legal notices and a small footer – your own account name gets top-billing in the message alongside your logo in your own colours and fonts, so there's little chance that your recipients will be confused by it.
While we try to support as many different web browsers as possible, some make it very difficult, in particular Internet Explorer 6, 7 and 8. If you an old version of IE, you may find our site slow or not particularly pretty in some places.
Some browsers are over 80 times faster than ~IE6, so we highly recommend that you upgrade to a browser less than 13 years old, such as a current [[Internet Explorer|http://windows.microsoft.com/en-gb/internet-explorer/download-ie]], [[Firefox|http://www.mozilla.org/en-US/firefox/new/]], [[Chrome|https://www.google.com/chrome/browser/]], [[Opera|http://www.opera.com/]] or [[Safari|http://www.apple.com/safari/]].
CSS inlining is a way of helping your messages render better in email clients that have poor CSS support, principally gmail and outlook. It is a somewhat destructive process and it's unfortunate that we need to resort to such measures, but we have to live with it.
!!What is inlining?
Normally HTML is styled using a CSS style sheet. This defines rules that are applied to the HTML that matches the selectors. For example the CSS rule:
{{{
p { color: red; }
}}}
would make all {{{p}}} (paragraph) tags use red as their text colour. The advantage of this mechanism is that it applies to all {{{p}}} tags, anywhere in the document, and it only needs to be defined in this one place, making it very simple to change it to another colour should you want to do so. These styles are usually placed in a {{{style}}} tag within the {{{head}}} tag of an HTML document.
It's also possible to apply styles directly within HTML using the style attribute on any tag, for example:
{{{
<p style="color: red;">Hello!</p>
}}}
This would make the text of ''only'' this paragraph appear in red; no other {{{p}}} tags would be affected. This approach is called an ''inline style''. If you did this on every paragraph, they would all appear in red, but if you wanted to change the colour, you would have to alter all of them separately.
CSS inlining is the process of converting the styles in a {{{style}}} tag into inline styles on the tags they select. Here's a larger example:
{{{
<html>
<head>
<style>
.para {
background-color: blue;
color: white;
}
</style>
</head>
<body>
<p class="para">Hello</p>
<p class="para">There</p>
<p class="para">Everybody</p>
</body>
</html>
}}}
Would be converted to this:
{{{
<html>
<head>
</head>
<body>
<p class="para" style="background-color: blue; color: white;">Hello</p>
<p class="para" style="background-color: blue; color: white;">There</p>
<p class="para" style="background-color: blue; color: white;">Everybody</p>
</body>
</html>
}}}
!!Why is inlining needed?
Some email clients, principally gmail, remove some vital parts of your messages that means that style tags cannot work properly. Generally they do still work with inline styles, so we need to convert style sheets into inline styles in order to preserve the appearance of your messages in such clients.
!!What are the disadvantages of inlining?
There are some downsides to inlining. Firstly it makes your template much larger, effectively rendering it uneditable – styling changes become extremely difficult after the inlining process, so you need to work with style sheets until the last possible moment. Smartmessages makes this easier by keeping your style sheets intact and applying inlining for you dynamically as messages are sent.
Inlining styles also makes messages bigger – in the above example, it adds 20 characters to every style tag – and that's just one simple style on one tag. It can often more than double the size of a template, which slows delivery and client downloads, imposes more load on mobile networks (for which the recipient may be paying).
There are also some aspects of CSS that don't work as inline styles. these are principally psueudo selectors, which handle things like hovering over buttons, and more significantly media queries, which is what allows email messages to be made responsive and format differently according to screen size. All is not lost here however – most email clients on mobile devices support style sheets correctly, so these will remain working if they are left in place.
!!Inlining in Smartmessages.
By default, Smartmessages does ''not'' inline styles – that decision is left to you as you may prefer to do without inlining, or prefer to use some other inliner. It can however be enabled at the template or mailshot level. When you create a template on the template page, you'll find a checkbox on the HTML tab to enable style conversion when sending:
[IMG[images/convertcss.png]]
If this box is checked for a template that you copy into a mailshot on the send page, the mailshot will inherit the template's setting, though you can override it if you wish. You will find that some of the standard library of templates provided by Smartmessages will have this option enabled. There's a similar checkbox on the send page if you want to override the template's own setting.
When converting style sheets to inline styles, Smartmessages //will remove the original style sheet//, except for any sections within media queries, which are left intact. The Smartmessages inliner also lacks suport for the universal {{{*}}} selector, though with good reason – it's possible to cause a message to balloon to many hundreds of times its original size if that selector is used.
!!!When is inlining applied?
This is an important point – inlining is ''only'' applied to ''email messages'' as they are sent. It is ''not'' applied to mailshot or template previews or web versions linked from messages. This is because it's not necessary to apply inlining to web versions since they are always viewed in web browsers, which do not have the shortcomings of email clients when viewing messages. Because of this, it's ''especially important that you test your mailshots by sending test mailings'', not just by looking at browser previews; the way that email clients handle CSS is often radically different to how browsers do, so viewing it in a browser is ''not'' representative.
As a simpler alternative to using our API, you may be well-served by our callback system. Instead of writing scripts to interrogate our system, we can tell you when something happens in your account, without you having to keep asking (polling). Callbacks are also known as web hooks, and you can [[read more about them here|http://wiki.webhooks.org/]].
On your account settings page, you can enable callbacks, provide us with the URL of a script on your site that should receive these callbacks, and select the events that you'd like to receive callbacks for. It's an efficient mechanism because traffic is only generated when something happens, but at very busy times you may have a lot of requests coming your way!
[IMG[images/callback.png]]
Callbacks are ideal for posting events into CRM systems. For example when someone clicks on a link, it could put them into a follow-up contact queue for sales staff in your CRM.
!URL pattern
Your script can be on any vaild domain, with any path; The only real restrictions are that your URL should be valid and should not contain a query string (starting with {{{?}}}) or an anchor location/fragment (starting with {{{#}}}), and not be in a private or inaccesssible network (e.g. {{{192.168.*}}} or {{{localhost}}}). Of course you don't have to implement your handler in PHP – you can use any language you like – and it's generally very easy to implement handlers for the straightforward requests we use (see example below). A simple callback URL might look like this:
{{{
https://www.example.com/callback.php
}}}
We also support HTTP basic authentication with a username and password, e.g.
{{{
https://user:pass@www.example.com/callback.php
}}}
If you don't use password protection, you can improve the security of your script by giving it a less guessable name, for example:
{{{
https://www.example.com/callback924a8ceeac17f54d3be3f8cdf1c04eb2.php
}}}
If you really can't use HTTPS, we will also send to unencrypted HTTP ~URLs:
{{{
http://www.example.com/callback.php
}}}
!Security
There's no reason not to use HTTPS any more (it's free, faster than without), so you should be using it as a matter of course for callbacks, especially since they can be used to transfer personal data. Note that we do insist on verifiable certificates for HTTPS connections.
It's important that you verify that the callback requests you receive have really come from us, and not someone pretending to be us. To enable checking that, you will find a custom HTTP header called {{{Smartmessages-Callback-MAC}}} in all callback requests we send. This is a [[Message Authentication Code|https://en.wikipedia.org/wiki/Message_authentication_code]] (''MAC'') that is calculated using the raw POST data in the request and your account's API key as the secret (visible on your account settings page), and guarantees that the request a) can only have come from us, and b) has not been altered in transit – this is in addition to the guarantees that TLS provides. The MAC algorithm used is {{{HMAC-SHA512/256}}} (note this is ''not'' the same as {{{HMAC-SHA256}}} or {{{HMAC-SHA512}}}), and is presented as a hexadecimal string. This algorithm was chosen on the basis that it's very strong, very fast, is commonly supported, and is the default MAC in [[libsodium|https://download.libsodium.org/doc/]]'s {{{crypto_auth}}} authentication functions, which are available in almost all common programming languages. Here's an example of how to verify the MAC using PHP:
{{{
$apikey = '<put your API key in here>';
$postdata = file_get_contents('php://input');
$MAC = hash_hmac('sha512/256', $postdata, $apikey);
$rMAC = $_SERVER['HTTP_SMARTMESSAGES_CALLBACK_MAC'];
//Use a constant-time comparison function, not just ==
if (!hash_equals($MAC, $rMAC)) {
header('HTTP/1.1 400 Bad Request');
echo 'Authentication failed; MAC mismatch';
exit;
}
}}}
This authentication is optional, and the data is entirely usable without authentication, but this measure is there for the protection of //your// data on //your// systems, not ours, so we strongly suggest you use and enforce it. Beyond verifying the callback's authenticity, it's in your interests to validate that the data you receive in each request looks like the documentation below describes before acting upon it, so as to avoid any other potential security issues. For example, force mailshot ~IDs to be integers. Our sample script applies some simple validation that you can build on.
!Events
These are the callback events that we can send you:
* {{{subscribe}}}
* {{{unsubscribe}}}
* {{{open}}}
* {{{click}}}
* {{{bounce}}}
* {{{spamreport}}}
* {{{mailshotstarted}}}
* {{{mailshotcomplete}}}
* {{{listuploadcomplete}}}
* {{{listuploadfailed}}}
* {{{delete}}}
Below you'll find descriptions of parameter names and values that will be supplied with each of these requests.
Requests from us will be in the form of a normal [[HTTP POST|http://en.wikipedia.org/wiki/HTTP_POST]] request using standard {{{application/www-form-urlencoded}}} encoding in the ~UTF-8 character set. In return, we expect a normal {{{HTTP/1.0 200 OK}}} success response (which is the default in languages like PHP, so you don't have to do anything special). We will also accept {{{201 Created}}} or {{{202 Accepted}}} responses. We give you 15 seconds to handle the request, but if your callback URL fails to respond, returns an error or a success code we're not expecting, we will retry the callback after 30 seconds, 10 minutes, 1 hour, and 1 day, after which we'll disable your callback and email all your account admins saying we've done so. We don't log bad responses and we ignore response bodies. ''It's up to you to make sure your system is available and working!'' When you've fixed your callback you can re-enable it on your account settings page. While callbacks are disabled, we don't queue any new events.
You can get and set your callback URL on your account settings page or via our {{{getcallbackurl}}} / {{{setcallbackurl}}} [[API|API]] functions.
!!Performance considerations
None of the CRM systems we've encountered are anywhere near fast enough to handle events at the full rate at which we can send events to you (hundreds per second); for example we found that salesforce.com takes up to two seconds to handle a single event. Some of our bigger customers receive peaks of 150 message openings per second alone, so please bear in mind these performance constraints when you are writing your script and selecting the events you want to receive as they will be coming thick and fast. A good way of dealing with 'peaky' traffic is to place the incoming callback requests into a queueing system (for example [[ZeroMQ|http://www.zeromq.org/]], [[beanstalkd|http://kr.github.com/beanstalkd/]] or [[Amazon's SQS|http://aws.amazon.com/sqs/]]) so you can process them at leisure rather than trying to handle them immediately; We use beanstalkd for our outbound queue.
We don't provide a 'send' callback event, but you can get a list of people that are on a mailing list used for a particular mailshot through our web interface or via our API; a more efficient batch operation instead of receiving send events.
!!Open
*//event//: The word 'open'.
*//address//: The email address that opened a message.
*//time//: The time this happened (~ISO8601 '{{{YYYY-MM-DD HH:MM:SS}}}' format, UTC time zone).
*//mailshotid//: The Smartmessages ID of the mailshot the message was in (compatible with API functions).
*//mailshotname//: The name of the mailshot the message was in (as shown on your mailings page).
*//ip//: The IP address of the user that opened the message.
*//agent//: The HTTP user-agent string of the user that opened the message.
Note that if the recipient has "Do Not Track" enabled, the {{{address}}}, {{{ip}}} and {{{agent}}} fields will be empty.
!!Click
*//event//: The word 'click'.
*//address//: The email address that clicked.
*//url//: The url they clicked.
*//time//: The time this happened (~ISO8601 '{{{YYYY-MM-DD HH:MM:SS}}}' format, UTC time zone).
*//mailshotid//: The Smartmessages ID of the mailshot the link was in (compatible with API functions).
*//mailshotname//: The name of the mailshot the link was in (as shown on your mailings page).
*//ip//: The IP address of the user that clicked the link.
*//agent//: The HTTP user-agent string of the user that clicked the link.
Note that if the recipient has "Do Not Track" enabled, the {{{address}}}, {{{ip}}} and {{{agent}}} fields will be empty.
!!Subscribe
*//event//: The word 'subscribe'.
*//address//: The email address that subscribed.
*//time//: The time this happened (~ISO8601 '{{{YYYY-MM-DD HH:MM:SS}}}' format, UTC time zone).
*//listid//: The Smartmessages ID of the list they subscribed to (compatible with API functions).
*//listname//: The name of the mailing list they subscribed to (as shown on your contacts page).
*//ip//: The IP address of the user that requested the subscribe.
*//agent//: The HTTP user-agent string of the user that requested the subscribe.
You won't receive subscribe events until subscriptions are confirmed via double-opt-in.
!!Unsubscribe
*//event//: The word 'unsubscribe'.
*//address//: The email address that unsubscribed.
*//time//: The time this happened (~ISO8601 '{{{YYYY-MM-DD HH:MM:SS}}}' format, UTC time zone).
*//listid//: The Smartmessages ID of the list they unsubscribed from (compatible with API functions).
*//listname//: The name of the mailing list they unsubscribed from (as shown on your contacts page).
*//ip//: The IP address of the user that requested the unsubscribe.
*//agent//: The HTTP user-agent string of the user that requested the unsubscribe.
!!Spam Report
*//event//: The word 'spamreport'.
*//time//: The time this happened (~ISO8601 '{{{YYYY-MM-DD HH:MM:SS}}}' format, UTC time zone).
*//address//: The email address that reported a message as spam.
*//mailshotid//: The Smartmessages ID of the mailshot (compatible with API functions).
*//mailshotname//: The name of the mailshot (as shown on your mailings page).
We only receive these from a few major ~ISPs, however it's vitally important to the health of your lists that you remove them at source as well as in Smartmessages (which happens automatically anyway).
!!Bounce
*//event//: The word 'bounce'.
*//time//: The time this happened (~ISO8601 '{{{YYYY-MM-DD HH:MM:SS}}}' format, UTC time zone).
*//address//: The email address that bounced.
*//reasoncode//: Our internal bounce reason code (See [[Bounces]]).
*//severity//: The bounce severity (hard, soft, other).
*//reason//: A text description of the bounce reason.
We only emit bounce callbacks when an address has received sufficient bounces to warrant removing it from lists. The point at which this happens is quite involved. For some ~ISPs (e.g. Yahoo!), a single hard bounce is considered fatal, for others an address may not be considered dead until several have been received. For this reason we don't emit callbacks for every bounce, only ones that result in an address being removed from lists, so in general you won't receive callbacks for soft bounces. In some cases the specific bounce reason stated may not sound fatal (e.g. mailbox full), but it may be the last in a long sequence of similar failures that has led to address removal.
!!Mailshot Started
*//event//: The word 'mailshotstarted'.
*//time//: The time this happened (~ISO8601 '{{{YYYY-MM-DD HH:MM:SS}}}' format, UTC time zone).
*//mailshotid//: The Smartmessages ID of the mailshot (compatible with API functions).
*//mailshotname//: The name of the mailshot (as shown on your mailings page).
!!Mailshot Complete
*//event//: The word 'mailshotcomplete'.
*//time//: The time this happened (~ISO8601 '{{{YYYY-MM-DD HH:MM:SS}}}' format, UTC time zone).
*//mailshotid//: The Smartmessages ID of the mailshot (compatible with API functions).
*//mailshotname//: The name of the mailshot (as shown on your mailings page).
!!List Upload Complete
*//event//: The word 'listuploadcomplete'.
*//time//: The time this happened (~ISO8601 '{{{YYYY-MM-DD HH:MM:SS}}}' format, UTC time zone).
*//listid//: The Smartmessages ID of the mailing list (compatible with API functions).
*//uploadid//: The Smartmessages ID of the upload (compatible with API functions).
*//listname//: The name of the mailing list (as shown on your contacts page).
!!List Upload Failed
*//event//: The word 'listuploadfailed'.
*//time//: The time this happened (~ISO8601 '{{{YYYY-MM-DD HH:MM:SS}}}' format, UTC time zone).
*//listid//: The Smartmessages ID of the mailing list (compatible with API functions).
*//uploadid//: The Smartmessages ID of the upload (compatible with API functions).
*//listname//: The name of the mailing list (as shown on your contacts page).
*//message//: A text message explaining why the upload failed, e.g. misnamed fields, corrupt file etc.
!!Subscriber deleted data
*//event//: The word 'delete'.
*//time//: The time this happened (~ISO8601 '{{{YYYY-MM-DD HH:MM:SS}}}' format, UTC time zone).
*//address//: The email address that deleted their data.
This event will happen when a subscriber makes use of our subscriber data access portal, accesses the data they have stored for you, and chooses to delete it all. This is their right under GDPR, and you should take appropriate action in your own systems, which may not necessarily imply deleting your own data relating to them.
!Example code
Here is a short PHP script to accept a callback request, apply some validation and log the data:
{{{
<?php
var_dump($_POST);
$apikey = '<put your API key here>';
if (!empty($apikey) && array_key_exists('HTTP_SMARTMESSAGES_CALLBACK_MAC', $_SERVER)) {
$postdata = file_get_contents('php://input');
$MAC = hash_hmac('sha512/256', $postdata, $apikey);
//Actual header name is 'Smartmessages-Callback-MAC' but PHP capitalises, converts - to _
$rMAC = $_SERVER['HTTP_SMARTMESSAGES_CALLBACK_MAC'];
//Use a constant-time comparison function, not just ==
if (!hash_equals($MAC, $rMAC)) {
http_response_code(400);
echo 'Authentication failed; MAC mismatch';
exit;
}
}
if (!array_key_exists('event', $_POST)) {
http_response_code(400);
echo 'Required parameters missing';
exit;
}
try {
$data = [];
switch ($_POST['event']) {
case 'subscribe':
if (array_keys_exist(
[
'address',
'time',
'listid',
'listname',
'ip',
'agent'
],
$_POST
)) {
$data['event'] = $_POST['event'];
$data['address'] = filter_var($_POST['address'], FILTER_VALIDATE_EMAIL);
$data['time'] = substr(preg_replace('/[^ 0-9\:-]/', '', $_POST['time']), 0, 19);
$data['listid'] = (int)$_POST['listid'];
$data['listname'] = mb_substr(strip_tags($_POST['listname']), 0, 100);
$data['ip'] = filter_var($_POST['ip'], FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 | FILTER_FLAG_IPV6);
$data['agent'] = mb_substr(strip_tags($_POST['agent']), 0, 255);
} else {
throw new RuntimeException('Invalid subscribe: ' . var_export($_POST, true));
}
break;
case 'unsubscribe':
if (array_keys_exist(
[
'address',
'time',
'listid',
'listname',
'ip',
'agent'
],
$_POST
)) {
$data['event'] = $_POST['event'];
$data['address'] = filter_var($_POST['address'], FILTER_VALIDATE_EMAIL);
$data['time'] = mb_substr(preg_replace('/[^ 0-9\:-]/', '', $_POST['time']), 0, 19);
$data['listid'] = (integer)$_POST['listid'];
$data['listname'] = mb_substr(strip_tags($_POST['listname']), 0, 100);
$data['ip'] = filter_var($_POST['ip'], FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 | FILTER_FLAG_IPV6);
$data['agent'] = mb_substr(strip_tags($_POST['agent']), 0, 255);
} else {
throw new RuntimeException('Invalid unsubscribe: ' . var_export($_POST, true));
}
break;
case 'click':
if (array_keys_exist(
[
'address',
'url',
'time',
'mailshotid',
'mailshotname',
'ip',
'agent'
],
$_POST
)) {
$data['event'] = $_POST['event'];
$data['address'] = filter_var($_POST['address'], FILTER_VALIDATE_EMAIL);
$data['url'] = filter_var($_POST['url'], FILTER_SANITIZE_URL);
$data['time'] = mb_substr(preg_replace('/[^ 0-9\:-]/', '', $_POST['time']), 0, 19);
$data['mailshotid'] = (integer)$_POST['mailshotid'];
$data['mailshotname'] = mb_substr(strip_tags($_POST['mailshotname']), 0, 100);
$data['ip'] = filter_var($_POST['ip'], FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 | FILTER_FLAG_IPV6);
$data['agent'] = mb_substr(strip_tags($_POST['agent']), 0, 255);
} else {
throw new RuntimeException('Invalid click: ' . var_export($_POST, true));
}
break;
case 'open':
if (array_keys_exist(
[
'address',
'time',
'mailshotid',
'mailshotname',
'ip',
'agent'
],
$_POST
)) {
$data['event'] = $_POST['event'];
$data['address'] = filter_var($_POST['address'], FILTER_VALIDATE_EMAIL);
$data['time'] = mb_substr(preg_replace('/[^ 0-9\:-]/', '', $_POST['time']), 0, 19);
$data['mailshotid'] = (integer)$_POST['mailshotid'];
$data['mailshotname'] = mb_substr(strip_tags($_POST['mailshotname']), 0, 100);
$data['ip'] = filter_var($_POST['ip'], FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 | FILTER_FLAG_IPV6);
$data['agent'] = mb_substr(strip_tags($_POST['agent']), 0, 255);
} else {
throw new RuntimeException('Invalid unsubscribe: ' . var_export($_POST, true));
}
break;
case 'bounce':
if (array_keys_exist(
[
'address',
'time',
'severity',
'reasoncode',
'reason'
],
$_POST
)) {
$data['event'] = $_POST['event'];
$data['address'] = filter_var($_POST['address'], FILTER_VALIDATE_EMAIL);
$data['time'] = mb_substr(preg_replace('/[^ 0-9\:-]/', '', $_POST['time']), 0, 19);
$data['severity'] = mb_substr(strip_tags($_POST['severity']), 0, 100);
$data['reasoncode'] = (integer)$_POST['reasoncode'];
$data['reason'] = mb_substr(strip_tags($_POST['reason']), 0, 100);
} else {
throw new RuntimeException('Invalid bounce: ' . var_export($_POST, true));
}
break;
case 'spamreport':
if (array_keys_exist(
[
'address',
'time'
],
$_POST
)) {
$data['event'] = $_POST['event'];
$data['address'] = filter_var($_POST['address'], FILTER_VALIDATE_EMAIL);
$data['time'] = mb_substr(preg_replace('/[^ 0-9\:-]/', '', $_POST['time']), 0, 19);
} else {
throw new RuntimeException('Invalid spamreport: ' . var_export($_POST, true));
}
break;
case 'mailshotstarted':
case 'mailshotcomplete':
if (array_keys_exist(
[
'time',
'mailshotid',
'mailshotname'
],
$_POST
)) {
$data['event'] = $_POST['event'];
$data['time'] = substr(preg_replace('/[^ 0-9\:-]/', '', $_POST['time']), 0, 19);
$data['mailshotid'] = (integer)$_POST['mailshotid'];
$data['mailshotname'] = mb_substr(strip_tags($_POST['mailshotname']), 0, 100);
} else {
throw new RuntimeException('Invalid ' . $_POST['event'] . ': ' . var_export($_POST, true));
}
break;
case 'listuploadfailed':
if (array_keys_exist(
[
'time',
'listid',
'listname',
'uploadid',
'message'
],
$_POST
)) {
$data['event'] = $_POST['event'];
$data['time'] = substr(preg_replace('/[^ 0-9\:-]/', '', $_POST['time']), 0, 19);
$data['listid'] = (integer)$_POST['listid'];
$data['listname'] = mb_substr(strip_tags($_POST['listname']), 0, 100);
$data['uploadid'] = (integer)$_POST['uploadid'];
$data['message'] = mb_substr(strip_tags($_POST['message']), 0, 100);
} else {
throw new RuntimeException('Invalid listuploadfailed: ' . var_export($_POST, true));
}
break;
case 'listuploadcomplete':
if (array_keys_exist(
[
'time',
'listid',
'listname',
'uploadid'
],
$_POST
)) {
$data['event'] = $_POST['event'];
$data['time'] = substr(preg_replace('/[^ 0-9\:-]/', '', $_POST['time']), 0, 19);
$data['listid'] = (integer)$_POST['listid'];
$data['listname'] = mb_substr(strip_tags($_POST['listname']), 0, 100);
$data['uploadid'] = (integer)$_POST['uploadid'];
} else {
throw new RuntimeException('Invalid listuploadcomplete: ' . var_export($_POST, true));
}
break;
case 'delete':
if (array_keys_exist(
[
'address',
],
$_POST
)) {
$data['event'] = $_POST['event'];
$data['time'] = substr(preg_replace('/[^ 0-9\:-]/', '', $_POST['time']), 0, 19);
$data['address'] = filter_var($_POST['address'], FILTER_VALIDATE_EMAIL);
} else {
throw new RuntimeException('Invalid delete: ' . var_export($_POST, true));
}
break;
default:
//If we get here we've received an unknown callback type
throw new RuntimeException('Unknown callback type: ' . var_export($_POST, true));
}
//At this point you've got all the data, it's up to you what to do with it next
debug($data);
} catch (RuntimeException $e) {
http_response_code(400);
debug($e->getMessage());
}
function debug($message)
{
//Convert non-string messages to something printable
if (!is_string($message) && !is_numeric($message)) {
$message = var_export($message, true);
}
file_put_contents('callback.txt', $message . "\n", FILE_APPEND | LOCK_EX);
}
function array_keys_exist($keys, $array)
{
if (!is_array($keys)) {
return array_key_exists($keys, $array);
}
foreach ($keys as $key) {
if (!array_key_exists($key, $array)) {
return false;
}
}
//Didn't fail to find one, so must all be present
return true;
}
}}}
Background: #faf3e4
Foreground: #5d574a
PrimaryPale: #8cf
PrimaryLight: #18f
PrimaryMid: #0088cc
PrimaryDark: #014
SecondaryPale: #ffc
SecondaryLight: #fe8
SecondaryMid: #db4
SecondaryDark: #554E3E
TertiaryPale: #eee
TertiaryLight: #ccc
TertiaryMid: #999
TertiaryDark: #666
Error: #f88
Please contact us if you have any suggestions, complaints or general comments.
[[support@smartmessages.net|mailto:support@smartmessages.net?subject=Support Request]]
If you're a recipient who wants to be removed from a list, use the unsubscribe link in the message you received. They are there for a reason and will work far faster and more efficiently than anything we can do manually.
Continuous mailshots are a kind of auto-responder. You create a continuous mailshot just list any other mailshot, but under the 'To' tab, select a mailing list, and then check the 'Continuous mailshot' checkbox. When you send a continuous mailshot, ''no messages are sent to the existing list''. When someone subscribes to the list, they ''will'' be sent the message as configured within the mailshot.
[IMG[images/continuous.gif]]
This makes them ideal for sending a 'welcome' message to anyone that signs up for one of your mailing lists. You might normally send a monthly newsletter to your 'newsletter' mailing list, but you can set up a welcome message (using all the normal template features) to thank them for signing up. As their name suggests, continuous mailshots have no particular send time – new subscribers will be sent a message a few seconds after they subscribe. After they have been activated, you can pause/continue/stop continuous mailshots individually on the mailings page.
When you have a double-opt-in subscription policy, messages will only be sent after a double opt-in verification loop has been completed.
List uploads are exempted from continuous mailshots, so after uploading a list into a list that's being used by an active continuous mailshot, the new subscribers will ''not'' be sent messages.
We offer a range of customised projects, using Smartmessages at the centre, and then coding in custom forms, with a complete business process from start to finish.
[[DomainKeys|http://en.wikipedia.org/wiki/Domainkeys]] and its newer replacement [[DKIM|http://en.wikipedia.org/wiki/DomainKeys_Identified_Mail]] (~DomainKeys Identified Mail) are anti-forgery technologies that help prevent phishing and spam, and as such increase the trust in messages that use them. ~DomainKeys is now deprecated and should not be used for new deployments.
DKIM is a step beyond what [[SPF and SenderID|SPF]] can offer for forgery prevention, at the expense of some complexity. While SPF attempts to ensure that the //origin// of the message is not forged, DKIM ensures that the //content// of a message is not forged or altered, thus the two technologies complement each other nicely; DKIM is not in any way a replacement for SPF. For ultimate trust in your email, you should use both.
DKIM is a replacement for the older and less-capable ~DomainKeys, and we only implement DKIM in Smartmessages. Like SPF, it requires that you create records in your DNS server – how you achieve that will vary widely, but if you own your own domain, you should be able to access that through your registrar or DNS hosting service (incidentally, we highly recommend [[Gandi.net|http://www.gandi.net/]] for domain registration and DNS hosting).
!Why?
What follows may seem like a lot of effort, and all too complicated, so why do it? Well, since you're here, you're obviously interested in getting email in front of your audience, in their inbox, not their spam folder. DKIM can help this – although there is nothing preventing spammers from using DKIM (and some do), it means that the receiver knows that what you sent is what you meant to send, and that you are not lying about who you are (courtesy of SPF). That helps them to trust the messages they receive from you, which can, when coupled with a consistent reputation of not sending messages that are reported as spam, result in more reliable inbox placement. Some email hosts display a little icon to the user indicating that a message is from a trusted source, further enhancing trust in your subscribers.
There's another key reason: Yahoo!, one of the inventors and biggest supporters of DKIM, requires that we use DKIM if we want to receive [[spam reports|SpamReports]] about messages we send for you. ''This is the single biggest driver for improving your sending reputation, deliverability and list quality!'' Mail hosts that are known to pay significant attention to DKIM signed email include Yahoo! and Google, and more are adding it every day. It's rapidly becoming the case that ''if you don't use DKIM, you can pretty much forget about being able to deliver volume to any Yahoo! domains'', which includes some other large UK ~ISPs such as btinternet.com and talk21.com. Convinced? Read on...
!!What's the 'via' thing I see in gmail?
We sign all messages with DKIM: if you have our key configured in your DNS, we use that, otherwise we sign using our sending domain, {{{mail.smartmessages.net}}}. In the latter case, gmail will display your message like this:
{{{
From: Joe User joe@example.com via mail.smartmessages.net
}}}
If you set up our DKIM key, it will not display the {{{via...}}} part.
!!Which domain?
When you send messages through Smartmessages, you have the opportunity to enter a 'from' address, such as 'newsletter@example.com'. The DKIM records need to match the domain part (the bit after the '@', in this case 'example.com') of your from address. If you use several domains, you can create the same DNS records in each of them, and register them all in Smartmessages, and we will use the right one automatically. Note that you need to have control of the DNS for the domain in question.
!!What do I need to do?
If you don't already have DKIM in your DNS, you will need to create a DNS record with our DKIM selector ({{{sm2}}} for Smartmessages) that contains our DKIM key. Selectors allow different mail sources to sign messages independently, for example by different branch offices, or (gasp!) other mailing list management providers, each using their own selector.
Exactly how you change your DNS records will vary depending on what provider you use – you'll need to consult their help.
Create another TXT record and name it {{{sm2._domainkey}}}. The value of the record should be set to this:
{{{
v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqKmFo0mnBMoJeJYbVvwSOflmISd5jkKAO0xowlJUEE+PYHXt7hgHFqc7SiFj2sKN2R8xI4ifFgz/0zuVYUe9gGT4cpuVy1Gu746K+R5tSd7EmnXgZe2PFogu/b+YABjQaR9GpF7VuZCXXGyueCL75Pabx3QzRr8ZtIFIUfqNyhH2WlaodFQqfxiPbxmWMlNhs8/mXDtijlt7b56hrWHTq+Ash/ut4OB53cZF8PBxNt8eCJXrdV0aqqefFJzmFDVSFTykWZ63tL7VKYvrVEvKS2BwjRI0pqrfpnLFeQbNV6waUEPAFZOHa/FQr01jSh5BJtHPQHp8COBzYoTqjeBKaQIDAQAB
}}}
If your DNS software complains about this value, try prefixing the semi-colons with a backslash, like {{{v=DKIM1\; k=rsa\;}}}, leaving the rest unchanged.
!!Alternative selectors
For our more advanced deployment on [[smartmessages.eu|https://www.smartmessages.eu]], we have a 4096-bit key with a selector of {{{sm4}}}. If you want to use this, you will need to add a TXT record for {{{sm4._domainkey}}} with this value:
{{{
v=DKIM1; k=rsa; p=MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA1/YEXZnfu8oF6dKU5CUaxywPeOBGgirSu9VsvtU13WQt/r7VRCKlS1zjZfVaXOjyRsuHO4ub+1gZUVCi+xGtumhFj9CP4mBP6l24PO2tN/YRvUde/LEL2299Y0ogaCRqoVm//RSN1vb2BkAKMSgRqxYWbaxjOGY/kaTu2f5ZdijORqS0Nfe6FwiTtcxgKEJe1wqNXe3pB9NGGU1XyQlE24f7WTqFs5lCNcOu4qJFK057htqwm/rBJYay2nnDYHerpcxhky2RNTWBcsCFd6bpWm5GynJu1PTsrM8HWihwK+T7hq076oT7tUIP1UHuuLfqMXkqvRhrmD7ID3Nk5GiE5WKkcqOrnkaTozw4iL0oi3aHW3NJnmBDTKrvD3UHyiSDQwp2QiDT8UWhA/A57lxC7hyYU8rUs/dCOia3rfx0uLTtiu9XMyVdznDdlckH6Yqc1z1oHTJmGvRPaW+PVk0R0aF7U0ZG53M9Sd+efE5RGWrbe0qMsBYCSDJuQXFqu6kjRbUnyRC37v/lFOMSR7VVQ4wfL84vTQBvZRectiY1ol6Z/7rkAHfGyKbnTeKu9HGuLHwDhKrh/9stncok52aPvdlzSTi/5ZYMkIe6AzYsIDzObB9vu5niU4crMRk9gGDWVmgAvUGBFt+lF3kqCDgMOmIX5zOo1fbhqibLXUz9tHUCAwEAAQ==
}}}
The DKIM key for the {{{sm2}}} selector is 2048 bits in length. Some DNS systems may have trouble with large TXT records like this, but there are some workarounds for that. Firstly, many DNS servers may allow you to have multiple strings for a single record, in which case you should be able to split into two parts (usually in double quotes) like this:
{{{
"v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqKmFo0mnBMoJeJYbVvwSOflmISd5jkKAO0xowlJUEE+PYHXt7hgHFqc7SiFj2sKN2R8xI4ifFgz/0zuVYUe9gGT4cpuVy1Gu746K+R5tSd7EmnXgZe2PFogu/b+YABjQaR9GpF7VuZCXXGyueCL75Pabx3QzRr8ZtIFIUfqNyhH2Wl" "aodFQqfxiPbxmWMlNhs8/mXDtijlt7b56hrWHTq+Ash/ut4OB53cZF8PBxNt8eCJXrdV0aqqefFJzmFDVSFTykWZ63tL7VKYvrVEvKS2BwjRI0pqrfpnLFeQbNV6waUEPAFZOHa/FQr01jSh5BJtHPQHp8COBzYoTqjeBKaQIDAQAB"
}}}
Alternatively you can use the {{{sm1}}} selector and this 1024-bit key:
{{{
v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC5pjTQQoPqW+SwCw+QAbmI+uPuk1hPxYTummB4dtzw4QQLZZR8miTnHnmknKz+LMGMYioAHF2BvHjPsI4ixlFKo0ByyY32xfpF8V5TgdYciv8Bfrm1Iiinmlm5SvLOqP81TQ5G4hat7ccCsHP9gDJR/9J0ZV9gHHkzwBCLUK+njwIDAQAB
}}}
or for really limited systems, our original 384-bit key with the {{{sm}}} selector:
{{{
v=DKIM1; k=rsa; p=MEwwDQYJKoZIhvcNAQEBBQADOwAwOAIxALRHPRnFUks4Hntg7AidEbw3zZGWhVXAy4Gm6TiP1Ln96IwGV1Knde4bJClKTvsGTQIDAQAB
}}}
Note that Google (and possibly others) ignores DKIM signatures that have less than 1024 bits so we strongly recommend you upgrade to a longer key if you are using this old one.
If you set up multiple selectors we will automatically use the longest one, but you ''must verify it on the settings page''.
!!How do I know it's working?
Once you've set it up, you can check it (and everything else in your DNS) is working using a service like dnsreport. If you have a Unix/Linux/~MacOS X command line handy, you can try {{{dig txt _domainkey.example.com}}} and {{{dig txt sm2._domainkey.example.com}}} to check that your DNS is publishing your records correctly. Alternatively use [[this tool|http://domainkeys.sourceforge.net/policycheck.html]] for testing your policy, [[this one |http://dkimcore.org/tools/dkimrecordcheck.html]] for your selectors.
Once you've set up your DNS, you need to enter the domains you send from on the settings page of your Smartmessages account. When you do so, it will check SPF and DKIM entries and confirm that they are OK and what key length they are using. When you send correctly ~DKIM-signed messages to Yahoo! addresses recipients will see a small key-shaped icon next to your from address, indicating that it's validated.
!!!Here's one I made earlier
A complete set of DKIM and SPF DNS records for working with Smartmessages might look like this (exactly how it is presented will depend on your provider). This example contains both the {{{sm2}}} 2048-bit key and the legacy {{{sm}}} 384-bit key:
{{{
example.com. 10800 IN TXT "v=spf1 a mx include:smartmessages.net ~all"
_domainkey.example.com. 10800 IN TXT "o=~"
sm4._domainkey.example.com. 10800 IN TXT "v=DKIM1; k=rsa; p=MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA1/YEXZnfu8oF6dKU5CUaxywPeOBGgirSu9VsvtU13WQt/r7VRCKlS1zjZfVaXOjyRsuHO4ub+1gZUVCi+xGtumhF" "j9CP4mBP6l24PO2tN/YRvUde/LEL2299Y0ogaCRqoVm//RSN1vb2BkAKMSgRqxYWbaxjOGY/kaTu2f5ZdijORqS0Nfe6FwiTtcxgKEJe1wqNXe3pB9NGGU1XyQlE24f7WTqFs5lCNcOu4qJFK057ht" "qwm/rBJYay2nnDYHerpcxhky2RNTWBcsCFd6bpWm5GynJu1PTsrM8HWihwK+T7hq076oT7tUIP1UHuuLfqMXkqvRhrmD7ID3Nk5GiE5WKkcqOrnkaTozw4iL0oi3aHW3NJnmBDTKrvD3UHyiSDQwp2" "QiDT8UWhA/A57lxC7hyYU8rUs/dCOia3rfx0uLTtiu9XMyVdznDdlckH6Yqc1z1oHTJmGvRPaW+PVk0R0aF7U0ZG53M9Sd+efE5RGWrbe0qMsBYCSDJuQXFqu6kjRbUnyRC37v/lFOMSR7VVQ4wfL8" "4vTQBvZRectiY1ol6Z/7rkAHfGyKbnTeKu9HGuLHwDhKrh/9stncok52aPvdlzSTi/5ZYMkIe6AzYsIDzObB9vu5niU4crMRk9gGDWVmgAvUGBFt+lF3kqCDgMOmIX5zOo1fbhqibLXUz9tHUCAwEA" "AQ=="
sm2._domainkey.example.com. 10800 IN TXT "v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqKmFo0mnBMoJeJYbVvwSOflmISd5jkKAO0xowlJUEE+PYHXt7hgHFqc7SiFj2sKN2R8xI4ifFgz/0zuVYUe9gGT4cpuVy1Gu746K+R5tSd7EmnXgZe2PFogu/b+YABjQaR9GpF7VuZCXXGyueCL75Pabx3QzRr8ZtIFIUfqNyhH2Wl" "aodFQqfxiPbxmWMlNhs8/mXDtijlt7b56hrWHTq+Ash/ut4OB53cZF8PBxNt8eCJXrdV0aqqefFJzmFDVSFTykWZ63tL7VKYvrVEvKS2BwjRI0pqrfpnLFeQbNV6waUEPAFZOHa/FQr01jSh5BJtHPQHp8COBzYoTqjeBKaQIDAQAB"
sm._domainkey.example.com. 10800 IN TXT "v=DKIM1; k=rsa; p=MEwwDQYJKoZIhvcNAQEBBQADOwAwOAIxALRHPRnFUks4Hntg7AidEbw3zZGWhVXAy4Gm6TiP1Ln96IwGV1Knde4bJClKTvsGTQIDAQAB"
}}}
!!How do I register domains with Smartmessages?
Once you've set up your DNS, log into your Smartmessages account and go to the 'settings' tab in the 'account' page. At the bottom you will see an 'authenticated domains' section. Add your domain there and it will automatically check that your DNS contains the correct values. If you get some little red crosses instead of green ticks, double-check your DNS entries according to this guide, and you can use the 'recheck' button to try again. If you still have trouble, [[contact us|http://www.synchromedia.co.uk/about-us/contact-us/]]. Note that DNS changes can take a while to refresh (though additions are instant), so it may not give you the all-clear for several hours if you don't get it right first time.
!!How does it work?
DKIM uses [[public-key cryptography|http://en.wikipedia.org/wiki/Public_key_cryptography]], a technique which uses mathematically-related public and private keys to encrypt and decrypt data. Our public key (All that random-looking text in the DNS record) is placed in //your// DNS so that when an email is received (which contains an encrypted signature created using our //private// key), the email server can do a DNS lookup using our {{{sm2}}} selector and use the public key it finds there to verify that the email is legitimate and hasn't been tampered with in transit. The public key needs to be in //your// DNS in order to prove that //we// are not just making it up!
!!What if I don't set up DKIM?
You don't have to use DKIM; if you don't, we will still sign the message as an intermediary, which doesn't carry nearly as much weight as your own signature. It's rapidly becoming the case that ''if you don't use DKIM, you can pretty much forget about being able to deliver volume to any Yahoo! domains'', which includes some other large UK ~ISPs such as btinternet.com and talk21.com.
[[DMARC|http://www.dmarc.org/]] stands for "Domain-based Message Authentication, Reporting & Conformance", is a technical specification created by a group of organizations that want to help reduce the potential for email-based abuse by solving a couple of long-standing operational, deployment, and reporting issues related to email authentication protocols.
When you make use of email authentication protocols, specifically [[SPF]] and [[DKIM|DKIM and DomainKeys]], they describe how to identify whether a message has come from a valid source and whether it has been tampered with in transit. They don't say what to do when you encounter a message that fails these tests. Should you bounce it to the sender? Report it to the police? The problem is you don't really know what to do, and DMARC is here to address that. DMARC can be extremely effective; dmarc.org reports that twitter saw phishing attacks against them drop from 110 //million// per day to under 1000!
Generally setting up DMARC is quite similar to setting up DKIM, so you'll need to be familiar with creating new records in your DNS – we can help you with that. Most users simply set up a passive record that merely confirms that messages failing tests should be rejected, but it's interesting (especially if you have a high-value service that's prone to [[phishing|Phishing]] attacks) to get feedback on whether these attacks are occuring. You can set up your own system for that, but it's much easier to use a service for it – we recommend [[|Dmarcian.com|https://dmarcian.com/]].
Smartmessages is dedicated to protecting the rights of both account holders and subscribers, and we are fully transparent in our role. Data protection is something we have held dear for many years – as far as we are concerned, it is your //privilege// to be allowed to send email to your subscribers, a privilege that they must give to you explicitly, and that they are able to withdraw at any time. In light of that, we have always made the subscriber the focal point of our services, following a "privacy by design" doctrine dating back to the origins of Smartmessages in 2003. Here are some of the measures we take.
!Servers located in the UK
Our servers (dedicated and virtual) are located in London, owned and hosted by a UK company, in a ~UK-owned data centre. If you are currently using a non-EU ESP and have so much as a single EU data subject on your lists, this is an important consideration. When the [[safe harbour agreement|https://en.wikipedia.org/wiki/International_Safe_Harbor_Privacy_Principles]] collapsed in October 2015, it became illegal (in the absence of any explicit consent) to store data on EU citizens in the USA. That continued until July 2016, when the [[Privacy Shield|https://en.wikipedia.org/wiki/EU-US_Privacy_Shield]] mechanism came into force. Privacy Shield, as expected, [[collapsed in 2020|https://noyb.eu/en/cjeu]]. This means that ''using ~US-based ~ESPs is now illegal in the EU'', and this is unlikely to change any time soon Other cases involving the US government vs Microsoft and Yahoo have suggested that hosting on an ~EU-based data centre belonging to a ~US-based hosting provider (for example AWS, Azure, Google cloud) may also be inadequate from a privacy point of view.
Brexit presents an additional set of challenges; the UK is //very// likely to lose "data adequacy" with respect to the GDPR and the same "third country" status that applies to the US will apply to the UK. As a result we are planning to move our servers out of the UK in 2021.
!Encrypted everything
Everything we serve is ''always'' delivered over encrypted HTTPS – including images, scripts, styles, HTML, email messages. You can read [[more detail on our security measures|Security]]. You'll find our domains in HSTS preload lists, so modern browsers do not have to rely on trust-on-first-use to ensure strong encryption from the very first request.
!Content control
We serve redirects, images, and other content loaded remotely from a cookie-free domain ({{{smm.im}}}) with an extremely strict [[Content-Security-Policy header|https://content-security-policy.com/]] that prevents us serving much that can be used as a channel for malicious activity, such as scripts and styles:
{{{
Content-Security-Policy: default-src 'none'; img-src 'self'; media-src 'self';
}}}
!Double-opt-in
When someone signs up for a Smartmessages account, or subscribes to a mailing list, we send them a message containing a link that the recipient must click to verify the request before activating their subscription or account. This is called double-opt-in. This represents a small inconvenience and a minor obstacle for subscribers joining your lists, however, it delivers some important benefits:
* You have auditable proof that they signed up
* Mistyped, invalid or undeliverable addresses will never be added to your lists, improving long-term deliverability
* An enormous reduction in spam complaints because you're not sending to anyone who has not requested your messages
There are many marketers who say that double-opt-in isn't a requirement, and indeed strictly speaking, in the UK, //for business-to-business email//, it is not. However, the same regulations have also been used (in court) to stipulate that any address on a public ISP (e.g. gmail, hotmail, MSN, AOL, BT internet etc) must be considered a personal address, but that's difficult to identify, so we should err on the side of caution. PECR says that business-to-consumer email //does// require explicit opt-in. It is also a requirement in large portions of the EU, for example France, Germany, and Spain. To be strictly accurate, the regulations do not stipulate double-opt-in because that is a technical implementation detail, but they do specify that permission must be traceable and auditable, and double-opt-in is the //only available way// to achieve that – it's not possible to get that level of proof via opt-out or single-opt-in or "confirmed" opt-in (where a notification is sent but does not require positive action by the recipient), so anything short of double-opt-in is as bad as opt-out. The spam-reporting element should not be underestimated – a single spam report is enough to impair the deliverability of tens of thousands of other messages from you, so avoiding double-opt-in on the basis that it may make a small difference to the growth of your lists is a false economy.
All this skirting of the issue is also academic: it is a requirement of the [[PECR law|https://ico.org.uk/for-organisations/guide-to-pecr/what-are-pecr/]] (which will eventually be replaced by [[ePR|GDPR]]). While this has been represented as a major change, that's not the case – PECR has required verifiable consent since 2003 – but the penalties for non-compliance were weak and poorly enforced, so they were largely ignored. GDPR and ePR change that.
!Double-opt-in messages are retained
Since we want to support the most stringent protections we can, we have implemented a German requirement that we store not only double-opt-in data, but also a copy of the exact confirmation message sent to the subscriber. Almost all ~ESPs do not do this, and thus are not legal to use if you have any subscribers in Germany. Because we use [[DKIM|DKIM and DomainKeys]] to sign every message, we can provide cryptographic proof that these messages are genuine.
!Easy unsubscribes
It's vitally important to make [[unsubscribing|Unsubscribes]] quick and simple – if subscribers can't unsubscribe easily, they will probably report your message as spam instead, the worst possible outcome. Every mailshot message we send contains an unsubscribe link (added automatically if you didn't include one in your template). This points at an unsubscribe page where a subscriber is asked to confirm their unsubscribe via an additional click. We require this additional click because mail filters increasingly follow all links in a message to check for malware before delivering it to an inbox, and that would result in automatic unsubscribe if we did not require an additional click. Unsubscribe pages are delivered in multiple languages, automatically adapting to the language requested by the user's browser. We also support the standard {{{list-unsubscribe}}} message header to take advantage of unsubscribe features built in to mail client apps, using both email and HTTP protocols.
!Registered as a data processor
Organisations that handle data belonging to data controllers (that's you) are called data processors, and the UK data protection act 2018 requires that both controllers and processors are registered with the UK information commissioner, which we are (as [[Synchromedia Limited|https://ico.org.uk/ESDWebPages/Entry/Z7728189]]). When you agree to our terms and conditions when you sign up for a Smartmessages account, you are agreeing that Synchromedia may act as a data processor for you.
!Data subject access requests
One of the requirements of both the data protection act and the GDPR is that data subjects (principally your subscribers, but also you as an account owner) are able to obtain a copy of data stored about them, and may request corrections or deletion. This is called a "Subject Access Request", often abbreviated to SAR or DSAR (adding "Digital"). Many companies treat ~SARs as some kind of annoyance and make it unnecessarily difficult, try to impose charges etc, but it is fundamental right and so we make it as easy as possible. Anyone who is ever sent a message via Smartmessages is [[able to log in to our Subscriber portal|https://www.smartmessages.net/subscriber.php]] where they can view, edit, download, and delete all of their data.
!Cookies & tracking
We use no third-party tracking tools //whatsoever// on administrative or public-facing pages (for example subscribe & unsubscribe) that are part of the Smartmessages service. We use only essential session cookies that are deleted when you log out or close your browser window; nothing is retained across sessions. Because they do not involve off-site tracking or third parties, and our services will not operate without them, the one cookie we do set does not require consent, so we do not show cookie consent banners. These cookies have {{{httpOnly}}}, {{{Secure}}}, and {{{Samesite}}} flags set for maximum security. ''We do not use Google Analytics'' or any similar tracking service on [[our promotional site|https://info.smartmessages.net/]]; you will find ''no tracking cookies or scripts on any of our sites''. For subscribers, we honour the ~W3C standard "Do Not Track" option available in all modern web browsers; Opens and clicks by subscribers with DNT set are recorded & reported anonymously, with no link to individuals (see the Tracking matrix below).
!Subscriber tracking is disabled by default
By default, mailshot message opens and clicks are ''not'' tracked and reported. You can enable open and click tracking in your account settings, however, this is still subject to user consent when subscribing, and their browser's DNT policy. Users are asked for consent to track them on our subscription forms, though only if you enable tracking in your account overall; it's assumed to be disabled otherwise. When you choose to track users, we include a message saying so on your mailing list subscription pages and privacy policy.
!Anonymous tracking
When tracking //is// enabled, open trackers and redirects //are// used, however, these only contain a user identifier if we have received explicit consent from the user to track them. Furthermore, if we //do// have consent from the subscriber to track them, but their browser asks us not to track them via DNT, we do not track them. In these cases we //do// receive open and track data, but we discard the subscriber identifer and record the event anonymously, with no link to the subscriber. It's not just that we don't display this identifying data – we don't retain it at all.
One side effect of this approach is that the number of //unique// message opens or clicks will appear lower, because all opens and clicks performed by //all// anonymous users effectively act like //one// user. Counts of anonymous opens and clicks are shown in our mailshot reports. Total open and click counts are unaffected by anonymous users.
!Tracking matrix
The various tracking options interact with each other producing numerous combinations of effects. Opens and clicks have different characteristics because of where they occur. Here's how they all work together:
!!Message opens
|!Account tracking setting |!Subscriber tracking consent |! Effect |
|On |On |Fully tracked and identified |
|On |Off |Anonymously tracked |
|Off |On |Completely untracked |
|Off |Off |Completely untracked |
Note that DNT does not apply to opening trackers because they operate from directly inside email client programs (like Outlook, Gmail, or Apple Mail), whereas clicks go via the user's web browser. Historically only browsers provide control over do not track; email clients do not use it (if they start doing so, our systems would heed it automatically).
!!Message clicks
|!Account tracking setting |!Subscriber tracking consent |!Do not Track |! Effect |
|On |On |On |Anonymously tracked |
|On |On |Off |Fully tracked and identified |
|On |Off |On |Anonymously tracked (externally verifiable) |
|On |Off |Off |Anonymously tracked (externally verifiable) |
|Off |On |On |Completely untracked |
|Off |On |Off |Completely untracked |
|Off |Off |On |Completely untracked |
|Off |Off |Off |Completely untracked |
When a subscriber has not consented to tracking, the tracking that does occur is verifiably anonymous because the links that are used do not contain a user identifier. This is easy to check – compare the links in messages sent to two different subscribers in the same mailing, and note that they are identical, so we have no way to tell them apart. When tracking is disabled at the account level (the default), opening tracking images are not inserted at all, and links do not go via a redirect; it is completely untracked.
!!Why treat tracking this way?
GDPR and the UK Data Protection act includes a set of fundamental principles. Two of these are:
* "Personal data shall be collected for specified, explicit and legitimate purposes and not further processed in a manner that is incompatible with those purposes"
* "Personal data shall be adequate, relevant and limited to what is necessary in relation to the purposes for which they are processed"
The first of these means that if you collect personal data, you must say why you are collecting it and how it will be used, and //you must not use it for anything beyond that description//. The second says that you must only collect data that is required for you to carry out the operations that you described in the first requirement. When someone subscribes to a mailing list, the only thing they are consenting to (because it's all you're asking them for) is for you to send them email messages. If you collect that information and then use it for other purposes, such as tracking their activities, this is beyond the scope of what consent was obtained for, and thus not permitted.
Not heeding these requirements falls foul of another principle:
* "Personal data shall be processed lawfully, fairly and in a transparent manner in relation to the data subject"
Sneakily tracking users without their knowledge is clearly not fair or transparent, and as a result, is not lawful either.
There are two ways to comply with these requirements:
# Don't collect data other than their email address and live without tracking.
# Ask for tracking consent explicitly at the same time as you request consent to send them email.
We figure most of our customers would //like// to have tracking data, but it's a privilege that requires consent, so we provide the second option. Because consent for this type of processing must be explicit, it must default to "off", which also aligns with GDPR's article 25, "Data protection by design and by default", and also its "privacy by design" principles.
!Data sharing
As mentioned above, we act as a data processor for whoever owns the mailing lists that subscribers subscribe to. As such we do not have any ownership of the data, and hence ''we do not share data with anyone else at all'', including Facebook, Google, Twitter, or other data sellers. It is possible for senders to embed tracking elements such as Facebook "like" buttons in the messages we send for them, however, the data from these never touches our systems, and subscribers should block them using browser ad-blocking tools.
!Data retention
We retain data on subscribers for as long as they hold active, verified subscriptions; otherwise we cannot fulfil the function we have been asked to do. After a subscription becomes inactive, data is retained for 6 months before being deleted. After that, all data is anonymised and turned into aggregate statistics with no way of recovering information on individuals. Unsubscribe data is retained so that we can still perform long-term suppression (preventing subscribers that have unsubscribed from being being added back to lists) .
Smartmessages account holders may request deletion of their account (and all related subscriber data) at any time, but some legislation imposes limits, for example ~CAN-SPAM requires us to record unsubscribe requests for 30 days after the last mailing, which we can't do if the data is no longer there.
!Data portability
A requirement of the GDPR is data portability, which means that as an account holder, you must be able to export your data in a form that can be transferred to another service provider. We provide all the data that we store and capture for you in industry-standard [[CSV format|https://en.wikipedia.org/wiki/Comma-separated_values]]. An important feature of this is that exported mailing lists also include details of double-opt-in verification so you are able to retain evidence of permission. The same applies to subscribers, so individual subscriber data is also downloadable in CSV format through our subscriber data access portal.
If you have any concerns about data protection, please contact our designated data protection officer at [[privacy@smartmessages.net|mailto:privacy@smartmessages.net]].
This happens under the contacts tabs. All files can be opened by Excel (CVS).
[IMG[images/contact.gif]]
1. Click the ''manage'' button: [IMG[images/manage.gif]]
2. Click the ''actions'' tab: [IMG[images/list.gif]]
3. Cick the ''download list'' button:
[IMG[images/download.gif]]
Email addresses are surprisingly complex and tricky things, and there are many addresses that you might not think are valid that are, and vice versa. For example, this is a valid email address: {{{!#$%&'*+-/=?^_`{}|~@example.org}}}, but this is not: {{{joe_user@example_site.org}}}. Many web sites don't understand this and reject some perfectly valid addresses, much to the annoyance of their users. This is especially common for the '+' character which is used when creating extremely useful 'disposable' addresses such as {{{user+something@example.com}}}, something that is supported on Gmail, Yahoo! and Hotmail/Live. You can name and shame sites that don't know what email addresses look like [[here|http://youdontknowemail.tumblr.com]].
That said, many strictly valid email addresses are unlikely to be correct, so it's common to only allow a subset, but any validation should //never// allow something that is really invalid, no matter what subset is chosen (for example it's always invalid for a domain to contain an underscore).
It's important to note that an address that's valid doesn't necessarily exist (i.e. it may still bounce if you email it), though an invalid address is guaranteed not to exist, so it's not worth sending to in the first place.
The applicable standards for email addresses are the original [[RFC822|http://tools.ietf.org/html/rfc822]] and its updates from ~RFCs [[2822|http://tools.ietf.org/html/rfc2822]] and [[5322|http://tools.ietf.org/html/rfc5322]], and related definitions in [[RFC821|http://tools.ietf.org/html/rfc821]], [[2821|http://tools.ietf.org/html/rfc2821]], [[5321|http://tools.ietf.org/html/rfc5321]] and [[1035|http://tools.ietf.org/html/rfc1035]]. ~RFC822 on its own isn't very useful for validation because it's missing updates and contains conflicts with these other standards.
!!Validation in Smartmessages
We avoid problems with invalid addresses by simply not allowing them into our system. They will be rejected in subscription requests, ignored (but reported to you) in list uploads etc. Smartmessages uses the definition of an email address from the [[official HTML5 specification of an email address|http://www.whatwg.org/specs/web-apps/current-work/#e-mail-state-(type=email)]], which we wrote.
!!Validating in your own code
You can use the {{{validateaddress}}} function in [[our API|API]] to check against the same validation we use internally, but we don't recommend that for high volumes as it's much more efficient to check addresses locally.
The most common way to validate in your own code is to use regular expressions, which is supported in almost all programming languages in some form. You'll find huge numbers of regular expressions for validating email if you search for them, but many are wrong, or at least wrong enough to be likely to annoy valid address holders or to allow invalid addresses. There are several validation expressions we recommend:
* [[Ex-parrot's RFC822 validator|http://www.ex-parrot.com/pdw/Mail-RFC822-Address.html]]. This is a complete ~RFC822 expression in perl, and shows just how horribly complicated a correct expression can be.
* [[Michael Rushton's PHP regex|http://squiloople.com/2009/12/20/email-address-validation/]]. This is also the expression used in [[PHPMailer|https://github.com/PHPMailer/PHPMailer]].
* [[PHP's built-in filter_var function|http://www.php.net/manual/en/function.filter-var.php]] with the {{{FILTER_VALIDATE_EMAIL}}} flag set. This is built-in to PHP 5.2 and later. It uses Michael Rushton's expression, with one change to not allow 'dotless' domains like 'a@b', which are not permitted by ICANN even though they are valid in ~RFC822.
* [[HTML5's email definition|http://www.whatwg.org/specs/web-apps/current-work/#e-mail-state-(type=email)]], which we wrote, attempts to provide a sensible compromise between allowing valid addresses and rejecting likely bad ones. This is what we are currently using within Smartmessages.
!!What is/are Emoji?
Emoji is a Japanese name given to a collection of unicode characters typically displayed as small pictures. Because they are characters just like the letters you are reading now, they can be used nearly anywhere that text can be. Emoji are distinct from older "emoticons" such as ":*)" as they typically comprise only a single special-purpose character, and of course, you don't need to turn your head to read them! Unlike most text, they are usually rendered in full-colour, and as they are vector-based drawings rather than bitmaps, they look sharp and smooth at any size, and they will usually be displayed even when images are off. Some examples:
* "Smileys" 😀😟😎
* Animals 🐼🐖🐷
* Celebrations 🎂🎃🎄❤️
* Zodiac signs ♊️♐️♍️
* Food 🍟🍺🍌
* Sports 🏂⚽️🏆
* Travel 🚃🚗🚲🚠
* Flags 🇬🇧🇺🇸🇫🇷
* Objects ⌚️📷📺💿📧
* Symbols ♻️♣️⛔️
* and not forgetting the ever-handy pile of poo 💩!
Recent changes in Unicode 7.0 added skin-tone variations and many more country flags, though their rendering varies quite a bit as they are still very new. In browsers that are up to speed, these will appear as single faces with different skin tones: 👨🏻👨🏼👨🏽👨🏾👨🏿 Browsers that have not caught up will either not display them at all, use some kind of placeholder character (often a white square or black diamond shape) or display each face with a colour swatch next to it.
!!Where can I use Emoji?
You can use Emoji in most places that you can use text, for example email subject lines, "from" name and message bodies (including plain-text), tweets and blog posts, but before you go jumping in, you need to bear your audience in mind because their appearance varies significantly. Older versions of Windows in particular have little or no support for them, Android was bad until recently, but Mac and iOS support has been excellent for a long time. There is also variation between browsers – Safari's support is great, Firefox less so, and Chrome and Internet Explorer only added them in 2015. You can see how they appear on different systems here. For maximum compatiblity, you can limit yourself to the "classic" range of Emoji, as shown [[here|http://classic.getemoji.com/]].
!!How can I get them?
In order to enter Emoji characters, it helps to have a character palette or keyboard layout that lets you choose them. Rather than explaining how to access them all here, we suggest you [[visit getemoji.com|http://blog.getemoji.com/]] which tells you how to insert Emoji characters on all modern operating systems. Alternatively, [[this page|http://getemoji.com/#_=_ ]] allows you to copy and paste Emoji characters.
Some systems can be 'upset' by Emoji characters, so sometimes they are entered by using a special plain-text markup of a character name surrounded by colons, for example {{{:smile:}}}, and these are known as 'shortcodes'. You can find a big list of these names on [[this Emoji cheat-sheet|http://www.emoji-cheat-sheet.com/]]. Popular users of this system include ~GitHub, Campfire, Basecamp, Zendesk and many others.
!!Emoji in Smartmessages
In Smartmessages you can use both native Unicode characters and the standard shortcodes in template and mailshot message bodies (both HTML and plain-text) and subject lines. We also support native Unicode Emoji (and all other unicode characters) in most other text fields including "From" names, mailing list names, mailshot and campaign folder names and so on, and also all subscriber fields (firstname, lastname, address, custom fields etc) where appropriate e.g., not in phone numbers or ~URLs! As always, you should test thoroughly before sending a big mailshot!
!!Handling Emoji data
This applies to all text handling, not just Emoji – you need to be sure you're using Unicode-aware software at every stage your data passes through – if you pass Unicode data through a non-unicode-aware app, such as older versions of Windows Notepad, it is very likely to completely wreck it! Notably, the ~MySQL database system's usual ~UTF-8 support is insufficient to store Emoji – you need to make sure you use the {{{utf8mb4}}} character set for any fields that may contain Emoji.
Smartmessages provides a file manager for handling your uploaded and imported images and PDF files – you can find it on the main tab bar labelled ''Files''. This is based on a popular web component called [[CKFinder|http://cksource.com/ckfinder]] that we have customised.
[IMG[images/filemanager.png]]
The manager is divided into two main areas: a folder browser on the left, a file browser on the right and a small toolbar at the top. This is similar to Windows Explorer.
In the folder browser you'll find two entries: ''Library'' and ''Images''. The library area is read-only (you can't upload into it) and contains useful graphic components such as icons, separators, frames, logos, clip-art etc that are used by some of our template tags such as {{{[[video]]}}}, and that you are free to use in your templates.
!Uploading and organising your images
The images area is your own, for you to organise as you like. You can upload images directly into the Images folder, or create subfolders – it's a good idea to use subfolders if you use lots of images. To create a new subfolder, simply right click on the ''Images'' folder (or whichever existing folder you want to make the new folder in), select ''Create subfolder'' and give it a name.
Uploading is really straightforward – just drag and drop images from your computer into the files area in your browser, or alternatively click the ''upload'' button and select one or more images to upload from your computer.
You can move or copy files between folders by simply dragging and dropping files from the file area to the folders.
You may upload files with {{{.png}}}, {{{.jpg}}}, {{{.jpeg}}}, {{{.pdf}}} and {{{.gif}}} extensions.
!Editing images
At present the file manager only includes the ability to resize and rename your images. To do either, select an image in the file area, right click it and select ''Rename'' or ''Resize'' from the menu. When resizing you can either change the original file in place, or create a new file. We are planning on improving these abilties in future.
!Image ~URLs
When you reference images from your file area in your mailshot templates, you can use relative ~URLs such as {{{<img src="images/logos/logo.png">}}}, and they will resolve within your file area automatically. A similar process applies to library images which start with {{{library/}}}. This approach is compatible with the common practice of bundling a template file with its images within an images folder, making it really simple to import templates from tools like Dreamweaver.
While you can upload images with spaces in their names, you must be careful when referring to them in your templates as the names must be ~URL-encoded. So for example, this contains an invalid URL:
{{{
<img src="images/logos/my logo.png">
}}}
It should be:
{{{
<img src="images/logos/my%20logo.png">
}}}
Similar constraints apply to other non-English characters. While there is no fixed standard for ~URL-encoding foreign character sets in ~URLs, the //de facto// standard is to use ~URL-encoded ~UTF-8. Browsers may make it look as if ~URLs with foreign characters in are working, but in fact they are ~URL-encoded behind the scenes.
Generally you will not need to deal with this yourself since the mailshot editor handles this automatically, but you may run into it if you are building templates yourself or using tools that don't know about this!
!!Your custom domain
When you use a relative URL, it is converted to a complete absolute URL when messages are sent, because relative ~URLs cannot work in email. Rather than use our own domain, we use one that's based on your account name and append our deliberately short, nondescript {{{smm.im}}} domain name. You can see the domain nd root URL that your account is using at the top of the files page – in the example image above you can see that this "Smartmessages Demo" account is allocated a {{{smartmessages-demo.smm.im}}} domain.
!!Secure by default
When you use relative ~URLs domain, Smartmessages ''always'' generates encrypted HTTPS absolute ~URLs, guaranteeing you will not trigger "mixed security mode" warnings in receiving clients. Note that you may still get these warnings if you also host your own images on non-secure domains. You can of course reference these images with these absolute ~URLs directly if you like.
One other advantage of serving images from this custom domain is that they do not incur the overhead of cookies, reducing transfer size and giving a small performance boost to all your recipients.
!Using images in the mailshot editor
When you're editing a mailshot, you will often want to upload and insert images. In the editor there is an image button on the toolbar. When you click it you will first be shown a small dialog that lets you change settings for an individual image (URL, width, height, alt tag etc), but you will also see a ''Browse server'' button. Clicking this button will open the same file manager from which you can upload/organise/edit/resize/rename your images, but most usefully, select one to insert into your template. When you insert images this way, it will automatically use the relative URL pattern described above.
Several features are being considered for future releases:
* Automatic pre-send [[SPF]] checks and enforcement
* Dynamic list segmentation
* Always keeping an eye on developments in ~Javascript WYSIWYG text editors to improve mailshot editing.
* Multi-language support in the customer interface
* Brandable (white-labelling) user interface for agencies (it's already brandable for your subscribers)
* New UI with nested campaign data
''GDPR'' is the EU's ''General Data Protection Regulation''. GDPR represented a major shift in the data protection landscape in Europe and beyond. The laws were made final in April 2016, and came into force on May 25th, 2018. The UK committed to GDPR compliance, and implemented it in the UK Data Protection Act 2018. The ~EUR-Lex site hosts [[the full text of the GDPR law|http://eur-lex.europa.eu/legal-content/EN/TXT/?uri=CELEX%3A32016R0679]]. The closely related ''Regulation on Privacy and Electronic Communications'' (known as ''ePR'') is not yet final; in the mean time the 2003 [[PECR|https://ico.org.uk/for-organisations/guide-to-pecr/what-are-pecr/]] (based on the older electronic privacy directive) applies in the UK .
While many of GDPR's requirements may be new to some, very little has changed relative to previous laws. GDPR updates, clarifies, and makes regulations more consistent, while adding detail, and raising penalties for non-compliance. The fundamentals of applicable data protection laws have remained largely unchanged in spirit for many years, and GDPR doesn't change them that much, if you've been paying attention! Respect for our customers and their subscribers is paramount to our business – we wrote Smartmessages because we were dissatisfied with how other services handled data.
As a result, we're handling GDPR as part of our usual data protection efforts, and you can read more about that on our [[Data Protection & Privacy]] and [[Security]] pages.
Smartmessages' creator, Marcus Bointon, can often be found giving talks on data protection & GDPR at technical conferences in Europe and north America.
[[Google Analytics|http://www.google.com/analytics/]] is a quick and easy way to add tracking for end-to-end marketing feedback. While we track all that we can (opens and clicks), we have no way of knowing how that helps your bottom line. How would you like to be able to see how many people from your mailshots actually bought something from your web site? That's the kind of thing that Google Analytics can tell you.
[IMG[images/google.gif]]
!!Privacy concerns
If you are running a particularly sensitive list, or want to implement your own tracking system, you can disable all link, open and analytics tracking features of Smartmessages by unchecking the ''Track users'' checkbox you'll find on the ''Analytics'' tab on the settings page.
!How it works
When we handle a clickthrough for you (see [[Link Tracking]]), we check if the link is pointing at one of your analytics domains, we add some parameters to the clicked URL to let analytics know where the link came from before telling the user's browser where to go. For example, a link to {{{http://www.example.com}}} might be extended to {{{https://www.example.com?utm_source=smartmessages.net&utm_medium=email&utm_campaign=My%20mailshot&utm_content=12345}}} that is, we add in information to the link about which mailshot the click is associated with. When the browser gets to the destination site, the Google Analytics javascript spots the additional parameters on the incoming URL and adds it to the information that it logs. It then means that all activity that this particular user does can be linked to the fact that they came from the mailshot. Read [[Google's documentation|https://support.google.com/analytics/answer/1033867?hl=en]] on the parameters. This is how we set them:
|!Parameter|!Value|
|{{{utm_medium}}}|{{{email}}}|
|{{{utm_source}}}|{{{smartmessages.net}}}|
|{{{utm_campaign}}}|The name of the mailshot|
|{{{utm_content}}}|The ID of the mailshot|
!How to set it up
There are two parts to setting up analytics in Smartmessages. Firstly you need to go to your Smartmessages accounts settings page, select ''Analytics'', click the 'enable analytics' checkbox, enter the domains that you want to use analytics for, and then save your settings. You must use the exact domain that you use in your links, for example if you have links like {{{https://www.example.com/story1.html}}}, you would enter {{{www.example.com}}}, ''not'' just {{{example.com}}}. After that, all redirected links using that domain will get the additional parameters added dynamically as they pass through our redirector (see [[Link Tracking]] for detail on how this works). Domains not in your list will not get the additional parameters. The {{{campaign}}} property comes from the name you give your mailshot when you send it, and the {{{content}}} value is our internal ID for the mailshot, which you may find useful if you use our [[API]] or need to differentiate mailshots that have the same name.
The second step is to install Google Analytics on your web site. That's highly dependent on how your site is set up, but [[Google tells you how to do it|http://www.google.com/analytics/discover_analytics.html]]. Once it's done, you should find that you start to see (on the analytics site, not in Smartmessages) a proportion of your visitors as coming from email links, referred by us, ripe for further analysis. It's not a real-time service, so you'll find that there is some delay before stats start coming through.
!!Where to find the stats
In Google analytics you will find the clicks reported in two different places. Primarily you will find them under ''Acquisition'' -> ''All traffic'' -> ''Source/Medium'', where you will see data coming from us tagged as {{{smartmessages.net/email}}}. This view will give you overall stats of all traffic from each source. For a more detailed per-mailshot view, go to ''Acquisition'' -> ''Campaigns'' -> ''All Campaigns''. This will show you traffic from all source/medium combinations by name – you will find it easier to identify Smartmessages mailshots if you select ''Acquisition'' -> ''Source/Medium'' as the secondary dimension from the menu above the campaign list.
Gravatars are personalisation images provided by [[gravatar.com|https://www.gravatar.com]], which are commonly used by users of wordpress.com, and many internet forums. This service associates an icon with an email address, and can either be set by the user, or generated algorithmically, so every address gets a unique icon. As a privacy measure we serve Gravatar images via a proxy which means that your IP address is not exposed to gravatar.com, and thus you cannot be tracked by them. Here's an example of a custom icon set for {{{info@smartmessages.net}}}:
[<IMG[https://www.smartmessages.net/av/cb4119cab961918d4d1a0488878042b2.png?s=80]]
and here's a generated one for an address that has no predefined icon:
[<IMG[https://www.smartmessages.net/av/f211411290589aea573c916329ec8691?r=pg&d=identicon&s=80]]
We use gravatars in our admin interface, but you can also use them in email templates with the {{{[[gravatar size=16]]}}}, {{{[[gravatar size=32]]}}} and {{{[[gravatar size=64]]}}} template tags which render icons of 16x16, 32x32 or 64x64 icons respectively for the recipient's email address.
!!Optional parameters
The gravatar tag accepts several optional parameters:
|!Parameter |!Purpose |!Default value |
| {{{size}}} |Width and height of the generated icon (they are always square), in pixels|80|
| {{{rating}}} |Audiences that this gravatar is appropriate for, using the American film rating standard: {{{g}}}, {{{pg}}}, {{{r}}}, {{{x}}}|{{{pg}}}|
| {{{email}}} |The email address to generate a gravatar for|The recipient of the email|
| {{{default}}} |The icon style to use if the address does not have a custom gravatar. One of {{{404}}}, {{{mm}}}, {{{identicon}}}, {{{monsterid}}}, {{{wavatar}}}, {{{retro}}}, {{{blank}}}|{{{identicon}}}|
| {{{urlonly}}} |If present, this option will cause this tag to render to the URL of the gravatar image, otherwise it will render to a complete image tag||
The default behaviour is thus the same as saying:
{{{
[[gravatar email=$subscriber.email rating="pg" size=80 default="identicon"]]
}}}
There are several ways of using images in HTML email, in order of popularity:
* Attached images
* Linked images
* Embedded images
* Data ~URIs
* No images!
In short, we recommend that you use linked images, and that's the only approach that Smartmessages supports anyway! For the full technical rundown on why that is, read on.
!!Attached images
The most common way that any kind of files (including images) are used in email is as simple attachments – this is what usually happens when your Mum sends you her holiday pics, or a colleague sends you a Word document. Many email clients (Outlook, Apple Mail etc) will display these with the message, but there isn't any particular layout relationship between the message content and the images, they are just lumped together at the bottom of the message. Because the image data is sent with the message, messages tend to be large, occupying space on the receiver's mail server even if the recipient does not open the message. This is great if you're only sending files to a few people, but is very inefficient for more than that, especially if your open rate is low.
Within the message structure, the image data is encoded using a system called [[base64|http://en.wikipedia.org/wiki/Base64]] which allows the image to be sent safely through a communications system designed for text (i.e. email). A base64-encoded image attachment in an email message looks like this:
{{{
Content-Type: image/gif; name="pixel.gif"
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename=pixel.gif
R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==
}}}
Believe it or not, that is a transparent 1-pixel [[GIF-format|http://en.wikipedia.org/wiki/GIF]] image.
!!!Client support
Image attachments are supported by all email clients worth mentioning.
!!Linked images
Next most common is simple linked images. These work just like images on web pages, and the HTML markup is identical, for example:
{{{
<img src="https://www.smartmessages.net/img/smlogo256dk.png" alt="smartmessages logo" width="256" height="27">
}}}
The advantage of these is that the image data is not sent with the message, keeping the message size small; the image is only loaded when the message is opened. They can be placed in HTML layouts with precise control over size and position.
In email clients, the fact that these are loaded when a message is opened can be used to detect when a message has been opened, and Smartmessages uses exactly this mechanism. This is also why most email clients default to not displaying images, to improve default privacy, and to speed loading and display of the message, particularly on mobile devices where data connections may be very slow and possibly expensive for the recipient. If the images are very small (e.g. for bullet images or icons), the overhead of a round-trip to the server (in both time and data volume) can negate this advantage. An email client may use a cache much like a web browser does, so if you send a message with your logo in, the second time they receive a message from you they may not need to download your logo because they can use the cached copy they loaded last time.
!!!Client support
Image attachments are supported by all email clients worth mentioning, though images are likely to be hidden at least the first time you send to them.
!!Embedded images
This is a cross between the first two. When an image is attached to a message, it can be assigned an identifier (using a format that often looks similar to an email address) within the message structure like this:
{{{
Content-Type: image/gif; name="pixel.gif"
Content-Transfer-Encoding: base64
Content-ID: <12345@example.net>
Content-Disposition: inline; filename=pixel.gif
R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==
}}}
This allows an HTML layout within the same message to reference the image using similar markup to linked images, like this:
{{{
<img src="cid:12345@example.net" alt="pixel" width="1" height="1">
}}}
You can see that the value in the {{{Content-ID}}} header is used in the image URL with a {{{cid:}}} prefix and so the email client knows to look for the part with that ID to find the image data to display in the HTML layout.
This approach has all the downsides of normal attached images (particularly large message sizes), but gains control over layout as it is displayed via the HTML markup. It's quite common for embedded or attched images to be enabled by default (as they pose no threat to privacy), and because the image data is already loaded, the layout is usually displayed instantly in all its glory.
An advantage of this approach is that the HTML can make multiple references to the same content identifier, so if for example you have a logo image that appears in three places in the message, it only has to store a single copy of the actual data.
!!!Client support
Embedded images are supported by all email clients worth mentioning.
!!Data ~URIs
[[Data URIs|http://en.wikipedia.org/wiki/Data_Uri]] work in a very similar way to the previous type; the difference is where the image data is stored. A data URI embeds the image data directly into the URI itself, so our example HTML would look like this (using the same image data as the previous example):
{{{
<img src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" alt="pixel!" width="1" height="1">
}}}
This can work in email, but it has a number of major downsides – it has the same disadvantages as attached images, but because there is no identifier associated with the image data, it can't be referred to by another element – if you wanted the same image to appear 3 times, it would embed three copies of the image data. Data ~URIs are a relatively recent development; they are not supported at all in Internet Explorer 5-7, and IE 8 is limited to 32k of data, which is enough for a small logo or icon, but useless for photographs.
Data ~URIs are most often used in web pages to save round-trips to the server to load small images, and there is no real point in using them in email – if you want to include image data in your messages you're better off with embedded images as they are more compatible and allow for larger images.
!!!Client support
Data ~URIs have very patchy support. Outlook is particularly bad; data-uri images are not displayed when images are disabled, but they are not displayed if you then ask it to show images either!
!!No images!
As you will have gathered, there are tradeoffs in all of the above approaches. We mentioned that image display is usually disabled in email clients, so your carefully-crafted images often won't be displayed anyway. With the increasing use of mobile devices on slow networks, not using images at all has considerable advantages – messages go fast, recipients get messages quickly and see them exactly as you intended (i.e. not missing images!). It's possible to produce good looking messages using only fonts and solid colours (gradients in some cases) that avoid all of the above pitfalls. Of course, it may not be right for you – it wouldn't be much good for presenting your photo portfolio, but it might be perfect for a sale announcement. Like many things, it's usually good to aim for a compromise – make a message that looks good with no images, and add a couple of images that make it look great, but built so that the meaning and general impression is not lost if they are missing.
!!!Testing without images
Smartmessages lets you check how your messages look with images disabled – on the template and send pages, select "Preview (Images off)" from the preview menu.
!Data volume
Message size can make a difference to send speed and resource consumption for both sending and receiving. Here's a calculation assuming we're sending a mailshot of a 10k message using 90k of images to 100,000 subscribers, and we assume that 10% of recipients open the message. For image attachments and data URI approaches, we would need to send a total of:
{{{
(10,000 + 90,000) * 100,000 = 10,000,000,000 bytes = 10 gigabytes of data.
}}}
and all of that data must be sent regardless of whether or when messages are actually received or opened.
The linked image approach would result in a total of
{{{
(10,000 * 100,000) + (90,000 * 10,000) = 1,900,000,000 bytes = approx 2 gigabytes of data.
}}}
So the linked image approach allows sending to go 10 times faster (because about half of the data volume is only incurred after sending) and consumes 1/5 of the overall data transfer. That's good news for both us //and// your subscribers!
Link or click tracking is a popular feature of email marketing. By knowing what links people are clicking on, you get to know what interests they have, which are your most interesting products or articles, and when combined with web analytics, what return on investment you are getting with your email marketing efforts. However, because Smartmmessages is privacy first, ''all tracking is disabled by default''. If you want to enable "traditional" open and click tracking, you can enable it by checking the ''Enable tracking'' checkbox you'll find on the ''Analytics'' tab on the settings page.
See [[open tracking|Open Tracking]] for information on tracking message openings.
!!How does link tracking work?
Normally links point directly at their target pages, and you dont get to know when someone clicks on them. We take your links and rewrite them so instead of going directly to the target page, they first come to our servers where we record the click and then forward the user's browser to the intended target – this is called redirection. This is invisible to the subscriber as it looks just like a normal click on a link to them – but this is also what makes them a little insidious and why they are often considered a privacy invasion.
!!What links do you track?
By default, ''none''. If you enable tracking, we track all links within HTML templates – you don't have to do anything extra.
We don't ever track links to our unsubscribe pages – they're not very interesting and you can get unsubscribe data elsewhere.
We don't track links in plain-text templates as they are far too likely to break, and it's more important that visitors actually get to the target page.
!!URL Syntax
When we rewrite your ~URLs, we do so in a consistent pattern. We always use the {{{smm.im}}} domain for redirected links. These links contain three elements:
* An identifier for the mailing (so we know which mailing to associate the clicks with) of about 22 chars
* An identifier for the subscriber of about 22 chars, or an anonymous placeholder {{{_}}} if they have not given consent for tracking
* An encoded and signed URL
The resulting ~URLs follow ths pattern:
{{{
https://smm.im/z/<mailshot identifier>/<subscriber identifier or _>/<encoded and signed URL>
}}}
So a fully-tracked URL might look like:
{{{
https://smm.im/z/6yG3oC71vkdXHnQfbfZ8a7/1ndbFxfH201pNBcp2Toa7e/Y2h0dHBzOi8vaW5mM28uc21hcnRtZXNzM
}}}
and an anonymously tracked URL (you can see that the subscriber idenfifier is missing):
{{{
https://smm.im/z/6yG3oC71vkdXHnQfbfZ8a7/_/Y2h0dHBzOi8vaW5mM28uc21hcnRtZXNzM
}}}
Our overhead is thus about 50 characters and encoding adds some overhead to the embedded URL, so you should be able to use ~URLs up to about 180 characters long safely. Some email programs do not like ~URLs over 255 characters, and some will even break at 72 characters, so it's a good idea to keep your ~URLs as short as possible. That said, ~URLs longer than this will still work in many clients. We truncate ~URLs at 2048 characters before encoding – if you need them longer than that, you're probably doing something wrong!
!!What's allowed in a URL?
When a message is generated for sending, we enforce [[RFC2396|http://www.faqs.org/rfcs/rfc2396.html]] section 2.4.3 compliance (the standard for URL syntax) in link ~URLs, stripping any characters that are not allowed. These are:
* All control characters (line breaks, tabs etc)
* Spaces
* Reserved delimiters: |, {, }, \, <, >, ^, ' and ".
The only character set supported in ~URLs is ~US-ASCII, as defined in ~RFC2396 and [[RFC3896|http://tools.ietf.org/html/rfc3986#page-11]]. ~UTF-8 or any other character set is ''NOT'' supported. That means //you should not expect Chinese, Russian etc characters in your ~URLs to work//. Some browsers will try their best to make these characters work (and will often display ~URL-encoded characters in their native form, so there is no harm in URL encoding), and you mught be lucky, but generally speaking, any characters like this should be ~URL-encoded.
!!Suppressing tracking per link
If tracking is enabled but you want to exclude a link from being tracked, just add a {{{nosmtracking}}} keyword to the link, like this:
{{{
<a href="http://www.example.com/secretclicks.php" nosmtracking>I'm not tracked!</a>
}}}
The keyword will be removed during the send process, so your recipients will never see it, the link will not go via our redirector, and it will not appear on any reports.
!!Phishing warnings
You need to be careful not to use link text that looks like a URL as it may trigger anti-phishing defences ([[read more about phishing|Phishing]]). In those cases, either use the above feature to disable tracking on the URL, change the link text, or make the link go via another redirector/shortener such as [[bit.ly|https://bitly.com/]] or [[goo.gl|http://goo.gl/]]. For example, don't do this:
{{{
<a href="http://www.example.com/">http://www.example.com/</a>
}}}
because it will get turned into this:
{{{
<a href="http://smm.im/z/..........">http://www.example.com/</a>
}}}
so you end up with a URL as link text that does not match the URL it goes to, which looks like a classic phishing attempt. Construct your links more like this to avoid the misinterpretation:
{{{
<a href="http://www.example.com/">Our home page</a>
}}}
!!Is click tracking reliable?
Redirecting ~URLs is very common and generally extremely reliable, but there are some possible complications.
* Any broken links will remain broken after being redirected.
* ~URLs that are malformed to start with may get rewritten incorrectly.
* Links may be opened by things other than your recipients (such as spam filters), resulting in inflated click counts.
To deal with the first two, make sure you check your templates and mailshots with the validator and link checker we provide.
The last problem generally has a predictable pattern – these filters/bots tend to open every link in a message simultaneously, and they also usually do it immediately they receive the message – so if you have many subscribers that use this kind of filtering you can expect to see inflated click counts and a very sharp spike in activity as soon as the send goes out. It's also likely that clicks from these automated systems do not appear in your Google analytics reports because that relies on javascript support which these systems typically do not use. We report the number of clicks that we think have come from such automated services in our reports as 'suspected automated clicks'. These automated systems are fairly rare (used by about 1% of domains we see), but they are very 'noisy', so can have a large impact on your click counts, particularly if you have a large number of links in your messages. For example if you have a 10k list of which 1% of subscribers (100) are using such a filter, and you send a mailshot containing 10 links, you might expect to see 1,000 automated clicks recorded.
Automated systems that follow message links may work intermittently – checking every link in every email is an expensive operation that slows down legitimate deliveries, so you may find their occurrence varies enormously. For example they may cache the results of link checks so that they are only checked once per day, or once per email address. This is entirely open to individual implementations and we have no way of telling what they are doing.
!!Connecting with Google Analytics
Our link tracking is effectively only the first half of the story. We send links to your subscribers, they click them, we record that (if enabled) and deliver them to the target page, where our involvement ends. Of course as far as your /web site/ is concerned, that's just the beginning. [[Google Analytics|http://www.google.com/analytics/]] (and more privacy-focused solutions like [[Matomo|https://matomo.org/]] and [[Fathom|https://usefathom.com/]]) can give you insight into what your visitors do /after/ they arrive, and also tell you /where they came from/.
We provide [[Google Analytics integration|GoogleAnalytics]] to help you make the most of this, and can automatically tag your links so you know where they have come from. While Google Analytics is likely illegal to use in the EU, it actually presents little privacy exposure at this point. The data that is added to links contains only generic information about which mailshot a link is associated with, that it was sent by Smartmessages, and that it was sent via email; it does not include any user-specific data at all.
!!Life cycle of a click
This diagram shows how clicks are processed. As far as data collection goes, the significant events are the pink boxes. You can see that click data is collected in different ways at different times, and any breaks in the chain will result in discrepancies between data sources. It's possible for breaks to occur at nearly every step (many of which are outside our control), so you would expect more data points to be recorded near the beginning of the chain than at the end – and google analytics records are the very last step, and so will have the lowest yield. For example notice that the mail filter may not run javascript and thus does not feed into Google analytics; similarly, if your link points at a non-existent page, we will record the click, but you may not have an analytics record of the visitor arriving on the page.
[IMG[images/clicklife.png]]
!!Cookies?
We are somewhat surprised that we even have to say this, but we do not set cookies when browsers hit our redirects. In that scenario there is no opportunity for a subscriber to give their consent to tracking (because the process is hidden from the user) and it's legally required that they do so, however, this does not stop a large proportion of our competitors from doing exactly that. Did we mention that we are "privacy first"?
List hygiene is the term used for applying best practices to the collection and use of addresses on mailing lists. Key aspects of list hygiene are:
* Double-opt-in verification of subscriptions
* Quick, simple, accurate and persistent unsubscribe handling
* Sending content that matches subscriber expectations
* Removal and future suppression of spam reporters, bounces, and manual suppressions
* Keeping lists in regular use
* Not accepting group addresses (sales@, info@ etc)
* Compliance with technical email standards
Not heeding each of these will likely lead to various symptoms:
* Lack of double-opt-in will result in higher bounce rates (due to mistyped addresses), and higher spam reporting rates (because addresses can be subscribed without their knowledge or consent)
* Poor unsubscribe handling willl result in higher spam reports (users will report as spam rather than use a bad or hidden unsubscribe system)
* Poor bounce handling will result in deferrals (delivery delays) and possible blacklisting, especially from major ~ISPs like Yahoo.
* Irrelevant content results in spam reporting and unsubscribes, so don't send pet food offers to someone that signed up for hi-fi news.
* Not using lists for long periods will result in higher bounce rates, especially on b2b lists where people often change jobs.
* Group addresses just result in confusion – they are often forwarded to multiple recipients, some of whom may report messages as spam or unsubscribe, even though their colleagues may have requested a subscription legitimately. The DMA recommends not allowing group addresses.
* Technical compliance is obviously vital – if you send messages that are not correctly formatted, they are likely to be undeliverable (and bounce) or unreadable (and get reported as spam or just ignored).
Smartmessages has some unusual features for processing mailing lists. To find these, go to the ''Contacts'' tab, then click a ''Manage'' button for a list, then click the ''Actions'' tab, then look under ''Operations''.
[IMG[images/list_operations.png]]
!Copy Active
This operation creates a new mailing list containing all the active subscribers within the current list. By active, we mean that we have recorded at least one open or click for them during the last 6 months. This operation doesn't affect the current list at all, but makes a whole new list.
!Copy Inactive
This operation creates a new mailing list containing all the subscribers within the current list that have ''not'' been active during the last 6 months. This is not quite the opposite of ''Copy Active''; to qualify as inactive, a subscriber must have been sent at least one message in the last 6 months to which they did not respond (we did not record an open or click for them). This will not include new subscribers that have never been sent anything, nor old subscribers that have not been sent anything in the last 6 months. This operation doesn't affect the current list at all, but makes a whole new list.
!Duplicate List
No surprises here – this simply makes a complete, independent copy of the current list – perhaps if you're planning on doing other operations on it or want to take a point-in-time snapshot of who is on the list.
!Add a list
This is where things get a little more complex! This operation allows you to merge two lists together, without duplication. It merges the list you select from the menu into the currently viewed list. This operation //does// change the current list and can't be undone, so make a backup using the ''Duplicate list'' operation if you're worried! The addition of the two lists works like this:
|!Current list (before) |!Selected list |!Current list (after) |
|fred@example.com||fred@example.com|
||sarah@example.net|sarah@example.net|
|carol@example.org|carol@example.org|carol@example.org|
You can see that the resulting list contains anyone who was on either list, but only once.
!Subtract a list
This operation allows you to subtract one list from another. It removes any subscribers from the list you select from the currently viewed list. This operation //does// change the current list and can't be undone, so make a backup using the using the ''Duplicate list'' operation if you're worried! It does not affect the list you select. The subtraction of the two lists works like this:
|!Current list (before) |!Selected list |!Current list (after) |
|fred@example.com||fred@example.com|
||sarah@example.net||
|carol@example.org|carol@example.org||
In this case, {{{fred@example.com}}} remained on the list because he was not in the selected list; {{{carol@example.org}}} was removed because she was on the current list as well as the selected list, but {{{sarah@example.net}}} was not added to the current list because she was only on the subtracted list. There is now no overlap between the lists.
Unsurprisingly, a mailing list is a list of recipients you wish to send email to. Smartmessages doesn't stop at just the lists themselves, but also allows you to gather data about your recipients, so your customers are stored once along with their data, and their subscriptions to multiple lists are stored separately. This means that if you know that {{{fred@example.com}}} actually likes to be called "John", that fact will be available across all of your lists, not just one of them – your customer is your customer, not several different flavours of that customer. Most mailing list management services don't offer this independence, and suffer from fragmented and incomplete data as a result.
When you upload a mailing list, it is first filtered according to any active [[suppressions|SuppressionLists]] that may apply to it, so anyone that has previously unsubscribed, or has reported your messages as spam, will be removed on import.
You can make use of [[List Operations]] to help manage your lists.
At present we don't have dynamic list segmentation (e.g. mail the subset of a list that responded the last time you mailed them), but it's [[something we're working on|FutureFeatures]].
[[Start here]]
[[AccountSettings]]
[[UploadLists]]
[[DownloadLists]]
[[Templates]]
[[SendingMailings]]
[[Reporting]]
[[RepeatMailings]]
[[Payment]]
[[API]]
[[ContactUs]]
All content Copyright © 2023 [[Synchromedia Limited|https://www.synchromedia.co.uk/]]
Microsoft Word includes features for exporting nicely formatted documents as HTML. Unfortunately Word is to HTML what the Titanic was to safe travel. It's a total disaster and you should avoid using it if even remotely possible.
!Mitigating the disaster
Smartmessages has two places where you can set the complete HTML content of templates – in the template page and in the content editor when sending a mailshot. The former is really for those that understand and work with HTML (designers/developers), and we would not expect them to be using Word for design anyway. The latter is where you're morely likely to run into trouble. Fortunately the content editor has a special 'paste from word' button that cleans up most of the excess junk that Word adds, but it does require that you use it for it to work, and not just paste in your content as normal.
Word has two options when exporting to HTML "Web page" and "Web page, filtered". The latter option produces much better results.
There are some conversion services that can help you remove most of the bad markup from Word's HTML:
* [[WordHTMLCleaner|http://www.wordhtmlcleaner.co.uk]] cleans up HTML documents created using Word's "Web page" exporter.
* [[Textfixer.com|http://www.textfixer.com/html/convert-word-to-html.php]] provides a system for converting {{{.doc}}} or {{{.docx}}} Word documents directly into clean HTML in a much better way than Word itself does.
If you're working with templates, you'll find full details of our new template syntax in the TemplateGuide. If you've made templates for Smartmessages before, this article will tell you how to convert your syntax for the new system. It helps to be up to speed on the [[new syntax|TemplateSyntax]] before attempting your own conversion.
Generally speaking we have moved away from using one-off custom tags towards a generic way of using dynamic information in a consistent, logical way. This makes it much more obvious where data is coming from – for example, was the old tag {{{[[url]]}}} the URL of your own web site, or the URL of the recipient's personal site? It was actually the first of these, and you will now find these two possibilities as {{{[[$subscriber.url]]}}} and {{{[[$account.url]]}}} which is far clearer.
The new system moves more of the logic into your templates and makes them a little more verbose, but also gives you much more control – for example in our old system if you didn't like the facebook icons we provided, you had to hard-code everything yourself; now it will provide our icon as a default, but it's trivial for you to change it to your own image. Similarly, it's now easy to set your own text for an unsubscribe link if you don't like our default.
Another key difference is that we now support relative ~URLs for images in templates (to an extent), which keeps templates smaller and more flexible.
!Automatic conversions
During the upgrade to the new version, we will be converting all templates to use the new syntax anyway, but if you later import a template that uses old syntax, you can use the 'Convert from old format" checkbox on the templates page. We also attempt to spot old-format templates and apply this conversion automatically.
!Common elements
Many of our customers do not make much use of personalisation (you're missing a trick!), and only make use of a few common tags. Here's a table of the most common tags in old and new syntax:
|!Original markup |!New markup |!Notes|
|{{{[[informal_greeting|Reader]]}}}|{{{[[$subscriber.informal_greeting|default:"Reader"]]}}}|Makes use of {{{default}}} modifier|
|{{{[[formal_greeting|Reader]]}}}|{{{[[$subscriber.formal_greeting|default:"Reader"]]}}}||
|{{{[[firstname]]}}}|{{{[[$subscriber.firstname]]}}}||
|{{{[[lastname]]}}}|{{{[[$subscriber.lastname]]}}}||
|{{{[[opengraphtags]]}}}||No longer needed|
|{{{[[body]]}}}||No longer needed|
|{{{[[tracking_image]]}}}|{{{[[tracking_image]]}}}|No longer required – handled automatically|
|{{{[[unsubscribe_link]]}}}|{{{<a nosmtracking href="[[$mailshot.unsubscribe_url]]">unsubscribe</a>}}}||
|{{{[[unsubscribe_url]]}}}|{{{[[$mailshot.unsubscribe_url]]}}}||
|{{{[[webversion link]]}}}|{{{<a href="[[$mailshot.webversion_url]]">View web version</a>}}}||
|{{{[[webversion_url]]}}}|{{{[[$mailshot.webversion_url]]}}}||
!Complete conversion table
Here are all of our old tags and their new equivalents:
|!Original markup |!New markup |!Notes |
|{{{[[address1]]}}}|{{{[[$subscriber.address1]]}}}||
|{{{[[address2]]}}}|{{{[[$subscriber.address2]]}}}||
|{{{[[address3]]}}}|{{{[[$subscriber.address3]]}}}||
|{{{[[backcolour]]}}}|{{{[[$account.backcolour]]}}}||
|{{{[[body]]}}}||No replacement – edit content directly|
|{{{[[bodyfonts]]}}}|{{{[[$account.bodyfonts nofilter]]}}}||
|{{{[[campaign_id]]}}}|{{{[[$campaign.id]]}}}||
|{{{[[campaign_name]]}}}|{{{[[$campaign.name]]}}}||
|{{{[[companyname]]}}}|{{{[[$subscriber.companyname]]}}}||
|{{{[[country]]}}}|{{{[[$subscriber.country]]}}}||
|{{{[[county]]}}}|{{{[[$subscriber.county]]}}}||
|{{{[[custom1]]}}}|{{{[[$subscriber.custom1]]}}}|Similarly for custom2 – custom32|
|{{{[[customer_address]]}}}|{{{[[$account.address|nl2br nofilter]]}}}||
|{{{[[customer_companynumber]]}}}|{{{[[$account.companynumber]]}}}||
|{{{[[customer_email]]}}}|{{{[[$account.email]]}}}||
|{{{[[customer_name]]}}}|{{{[[$account.name]]}}}||
|{{{[[customer_phone]]}}}|{{{[[$account.phone]]}}}||
|{{{[[customer_url]]}}}|{{{[[$account.url]]}}}||
|{{{[[dear]]}}}|{{{[[$subscriber.dear]]}}}||
|{{{[[dob]]}}}|{{{[[$subscriber.dob]]}}}||
|{{{[[email]]}}}|{{{[[$subscriber.email]]}}}||
|{{{[[facebooklike]]}}}|{{{[[facebook_like]]}}}||
|{{{[[facebookpagebutton]]}}}|{{{[[if $account.facebook]]<a href="[[$account.facebook_pageurl]]"><img src="/library/socialmediaicons/facebook_32.png" height="32" width="32" border="0" alt="Visit our facebook page"></a>[[/if]]}}}||
|{{{[[facebookpageurl]]}}}|{{{[[$account.facebook_pageurl]]}}}||
|{{{[[firstname]]}}}|{{{[[$subscriber.firstname]]}}}||
|{{{[[footer]]}}}||No replacement|
|{{{[[forecolour]]}}}|{{{[[$account.forecolour]]}}}||
|{{{[[formal_greeting|Subscriber]]}}}|{{{[[$subscriber.formal_greeting|default:"Subscriber"]]}}}||
|{{{[[googleplus]]}}}|{{{[[googleplus_share]]}}}||
|{{{[[googlepluspagebutton]]}}}|{{{[[if $account.googleplus]]<a href="[[$account.googleplus_pageurl]]"><img src="/library/socialmediaicons/google_32.png" height="32" width="32" border="0" alt="Visit our Google+ page"></a>[[/if]]}}}||
|{{{[[googlepluspageurl]]}}}|{{{[[$account.googleplus_pageurl]]}}}||
|{{{[[gravatar16]]}}}|{{{[[gravatar size=16]]}}}||
|{{{[[gravatar32]]}}}|{{{[[gravatar size=32]]}}}||
|{{{[[gravatar64]]}}}|{{{[[gravatar size=64]]}}}||
|{{{[[header]]}}}||No replacement|
|{{{[[headingfonts]]}}}|{{{[[$account.headingfonts nofilter]]}}}||
|{{{[[imagebase_url]]}}}|{{{[[$account.imagebase_url]]}}}||
|{{{[[informal_greeting|Subscriber]]}}}|{{{[[$subscriber.informal_greeting|default:"Subscriber"]]}}}||
|{{{[[initials]]}}}|{{{[[$subscriber.initials]]}}}||
|{{{[[jobtitle]]}}}|{{{[[$subscriber.jobtitle]]}}}||
|{{{[[landing_url]]}}}|{{{[[$account.landingpage_url]]}}}||
|{{{[[lastname]]}}}|{{{[[$subscriber.lastname]]}}}||
|{{{[[linkedin]]}}}|{{{[[linkedin_share]]}}}||
|{{{[[linkedinpagebutton]]}}}|{{{[[if $account.linkedin]]<a href="[[$account.linkedin_pageurl]]"><img src="/library/socialmediaicons/linkedin_32.png" height="32" width="32" border="0" alt="Visit our LinkedIn page"></a>[[/if]]}}}||
|{{{[[linkedinpageurl]]}}}|{{{[[$account.linkedin_pageurl]]}}}||
|{{{[[linkedinshare]]}}}|{{{[[linkedin_share]]}}}||
|{{{[[logo]]}}}|{{{[[$account.logo]]}}}||
|{{{[[logourl]]}}}|{{{[[$account.logo_url]]}}}||
|{{{[[mailinglist_id]]}}}|{{{[[$mailinglist.id]]}}}||
|{{{[[mailinglist_name]]}}}|{{{[[$mailinglist.name]]}}}||
|{{{[[mailshot_id]]}}}|{{{[[$mailshot.id]]}}}||
|{{{[[mailshot_name]]}}}|{{{[[$mailshot.name]]}}}||
|{{{[[mailshot_timestamp]]}}}|{{{[[$mailshot.timestamp]]}}}||
|{{{[[message_timestamp]]}}}|{{{[[$message.timestamp]]}}}||
|{{{[[mobile]]}}}|{{{[[$subscriber.mobile]]}}}||
|{{{[[opengraphtags]]}}}||No longer needed|
|{{{[[options_url]]}}}|{{{[[$subscriber.options_url]]}}}||
|{{{[[phone]]}}}|{{{[[$subscriber.phone]]}}}||
|{{{[[postcode]]}}}|{{{[[$subscriber.postcode]]}}}||
|{{{[[posttown]]}}}|{{{[[$subscriber.posttown]]}}}||
|{{{[[privacy_url]]}}}|{{{[[$account.privacypolicy_url]]}}}||
|{{{[[rss_*]]}}}||Replaced by new [[RSS]] tag|
|{{{[[rss]]}}}||Replaced by new [[RSS]] tag|
|{{{[[sendtofriend]]}}}|{{{<a href="mailto:?subject=[[$message.subject|default:$account.name|escape:'url']]&body=[[$mailshot.webversion_url|escape:'url']]>Send to a friend</a>}}}||
|{{{[[sex]]}}}|||
|{{{[[staticshareurl_facebook]]}}}|{{{[[$mailshot.facebook_staticshareurl]]}}}||
|{{{[[staticshareurl_linkedin]]}}}|{{{[[$mailshot.linkedin_staticshareurl]]}}}||
|{{{[[staticshareurl_twitter]]}}}|{{{[[$mailshot.twitter_staticshareurl]]}}}||
|{{{[[styles]]}}}||No replacement|
|{{{[[subject]]}}}|{{{[[$message.subject|default:$account.name]]}}}||
|{{{[[subscribe_link]]}}}|{{{<a href="[[$mailinglist.subscribe_url]]">subscribe</a>}}}||
|{{{[[subscribe_url]]}}}|{{{[[$mailinglist.subscribe_url]]}}}||
|{{{[[title]]}}}|{{{[[$subscriber.title]]}}}||
|{{{[[tracking_image]]}}}|{{{[[tracking_image]]}}}|No longer explicitly needed in templates|
|{{{[[tracking_url]]}}}|{{{[[$message.tracking_url]]}}}||
|{{{[[twitter]]}}}|{{{[[twitter_share]]}}}||
|{{{[[twitterfollow]]}}}|{{{[[twitter_follow]]}}}||
|{{{[[twitterpagebutton]]}}}|{{{[[if $account.twitter]]<a href="[[$account.twitter_pageurl]]"><img src="/library/socialmediaicons/twitter_32.png" height="32" width="32" border="0" alt="Visit our twitter page"></a>[[/if]]}}}||
|{{{[[twitterpageurl]]}}}|{{{[[$account.twitter_pageurl]]}}}||
|{{{[[unique_message_id]]}}}|{{{[[$message.id]]}}}||
|{{{[[unique_recipient_id]]}}}|{{{[[$subscriber.id]]}}}||
|{{{[[unsubscribe_link]]}}}|{{{<a nosmtracking href="[[$mailshot.unsubscribe_url]]">unsubscribe</a>}}}||
|{{{[[unsubscribe_url]]}}}|{{{[[$mailshot.unsubscribe_url]]}}}||
|{{{[[url]]}}}|{{{[[$subscriber.url]]}}}||
|{{{[[urlencoded_email]]}}}|{{{[[$subscriber.email|escape:'url']]}}}||
|{{{[[webversion link]]}}}|{{{<a href="[[$mailshot.webversion_url]]">View web version</a>}}}||
|{{{[[webversion_link_personal]]}}}|{{{<a href="[[$message.webversion_url]]">View web version</a>}}}||
|{{{[[webversion_url_personal]]}}}|{{{[[$message.webversion_url]]}}}||
|{{{[[webversion_url]]}}}|{{{[[$mailshot.webversion_url]]}}}||
|{{{[[webversion]]}}}|{{{[[$mailshot.webversion_url]]}}}||
Smartmessages' new templating system has been a long time coming, but now it's here and ready to produce better results than ever before. So what's changed?
!How things used to be
Previously, we used a complex structure for building reusable templates where separate editors were provided for isolated areas of a host template – you couldn't edit the overall template itself when creating a mailshot, only the content areas. This was a mixed blessing: it prevented you from breaking your overall layout, but meant you couldn't really see what was going on, and while the overall layout could include personalisation tags, the editable content areas could not. This dual-layer approach promoted template re-use but we found that most of our customers didn't take advantage of it, and the creation of these editable sections was something that we had to do for you – it wasn't a public feature, apart from the limited {{{[[body]]}}} tag available in the template editor. It was also quite slow.
The tagging system was inconsistent and somewhat inflexible – for example we needed two separate tags to support an email address and a ~URL-encoded email address; the only tags that supported a default value were {{{[[informal_greeting]]}}} and {{{[[formal_greeting]]}}}, yet there were many other tags that would have benefited from options like these.
There was no opportunity for conditional content – displaying certain sections of your template only to specific recipients matching certain criteria.
There was no error reporting mechanism for template markup – if you made a mistake it would be silently ignored – that makes for a quiet life, but could result in mailings going wrong.
We had RSS support, but it wasn't easy to use, and wasn't very flexible.
This might sound bad, but it's been a workable system for many years, most of our customers didn't have much difficulty with these limitations, and it's broadly similar to what many of our competitors offer.
!The new system
!!Internal reorganisation
The new system is still built using the same [[Smarty|http://www.smarty.net/]]-based template engine, but the main change is that we've done away with the dual-layer templates. This alone improves performance substantially.
!!Mailshots independent of templates
Mailshots are no longer tightly-bound to the templates they use, so templates can be deleted without deleting the mailshots that have used them. A mailshot now takes a snapshot of the template when select it and then allows you to edit every aspect of it without impacting other mailshots that use the same template, and changing templates no longer has the ability to alter scheduled mailshots unexpectedly.
!!Simplified sending
The sending process has been simplified, requires fewer steps, and you get to see your whole message at once when editing it.
!!Instant testing
While you're editing, you can instantly send a test mailing (without stopping what you're doing) with just one click.
!!Powerful editing
Tag insertion is integrated right into the (newly updated) WYSIWYG editor, The editor knows what tags look like and helps prevent you making mistakes when editing.
!!Faster feedback
Previews do not require page reloads or new windows. Saving is automatic, and all the template testing features (link, image, spam, validation etc) that were previously only available to those building their own templates are now available to apply to your mailshots in one click.
!!Consistent tagging
Tag names, variables and elements are now neatly organised in a logical, consistent way, meaning you're more likely to be able to guess tag names, less likely to make mistakes, and the availability of modifiers gives you great control over tag output. Automatic escaping makes HTML corruption far less likely.
!!New tags
As well as a general clean-up of tag naming, there are some great new tags: a table of contents ({{{[[toc]]}}}) tag generates automatic intra-page links. The newly rewritten RSS support is far more flexible, and allows you to embed multiple feeds in one template. Good-looking image-free buttons are quick and easy to generate with the new {{{[[button]]]}}} tag.
!!Conditional content
Now you can make sections of your templates only visible to certain recipients, based on any data you have using {{{[[if]]}}} tags. This is a powerful way of providing ultimate personalisation, but also allows content that only shows on web versions – for example you can encourage new visitors to sign up without annoying those that already have.
!!Honest error reporting
We now provide detailed, accurate error reports on both template and mailshot pages, and you won't be able to send a mailshot if its template contains errors.
!!New social networking features
Share links are now super-easy to create, just a {{{[[share]]}}} away, compete with shiny new retina-ready icons!
!!New templates
A new template system wouldn't be complete without some new templates to exploit it! Our new standard, simple templates are built using Zurb's fantastic responsive email framework, [[Ink|http://zurb.com/ink/]]. Another benefit of the all-at-once approach is that we have much better compatibilty with templates imported from elsewhere. We're planning on adding conversion options for some competitors' formats that will make migration much quicker and easier.
!!Image library
Over the years we have buit up a library of images that are useful when building emails – for example social network icons and separators. This library is now available when you insert an image, so you can browse our library without having to worry about finding and uploading your own, though of course you can still do that too!
!How do the changes affect me?
The main way this affects you is that the template tags have changed, which means that your existing templates won't work. Fortunately we're not about to leave you dangling, so we have converted all your existing templates (and the mailshots that used them) to the new system. This does mean that you'll need to read our [[new template guide|TemplateGuide]] when you're building new templates from now on, but you should find that everything works as before – the "copy & edit" workflow remains the same.
!!Mailshots now use template snapshots
It's important to understand the new independence of mailshots from templates – editing a template after creating a mailshot that uses it will no longer change the mailshot. Don't expect the mailshot editor (the send page) to display a 'current template', because that concept no longer exists. If you change the template for a mailshot you're working on and want it updated, re-select it from the template picker.
!!Converting your own templates
If you've been using our old template syntax, you'll need to change your workflows and any snippets you may use – take a look at the [[New Template Conversion]] article for more details.
!!Custom built templates
Some of our customers have custom-built templates; These are the ones most affected by the template changes. If you copy & edit mailshots using templates that had large numbers of editable areas but that were not actually used, you will find you may get some empty content blocks that need deleting (and you'll typically be doing that anyway if you've copied a previous mailshot), but this does not affect new mailshots, nor does it affect web versions of previous mailshots.
!!API
The [[API|API]] itself is unchanged – but the templates that you use with it will need to use the new format.
!Help!
As always, we're here to help – we appreciate that there are big changes in here that may cause you some issues, so please [[contact us|ContactUs]] if there's anything you need help with.
Like [[link tracking|Link Tracking]],open tracking is a popular feature of email marketing. By knowing that your subscribers have opened your messages, you get to know that they found your messages interesting enough to open. However, because Smartmmessages is privacy first, ''all tracking is disabled by default''. If you want to enable "traditional" open and click tracking, you can enable it by checking the ''Enable tracking'' checkbox you'll find on the ''Analytics'' tab on the settings page.
!!How does open tracking work?
Tracking the opening of your messages uses something called a "web bug", "pixel", or "beacon" image. When a message is opened, many email clients (Outlook, Gmail, Apple Mail) load the images that are referenced in the HTML. One of these images is usually a tracking image, and the URL it is loaded from contains information that can identify which message has been opened, when, and by whom. This is invisible to the subscriber as it looks just like a normal click on a link to them – but this is also what makes them a little insidious and why they are often considered a privacy invasion – in fact the reason that images are not loaded by default in most clients is almost entirely because users don't like being tracked.
!!How can I use open tracking?
When using our standard templates, you don't need to do anything, but when creating your own you have a choice of two function tags that will generate a tracking image. When you import your own templates, it will automatically have a tracking image inserted just before the closing body tag.
If you don't like the image tag that we generate for you, or it causes layout issues in the location it's placed, you can create your own using the {{{[[$message.tracking_url]]}}} tag and it will be used instead of our automatic tag. This tag renders to just a URL, so you need to embed it in an image tag for it to work, like this:
{{{
<img src="[[$message.tracking_url]]" width="1" height="1" alt="*">
}}}
You can place this anywhere you like in your layout. Make sure that your HTML editor doesn't rewrite the tags with URL encoding as that will break the template tag. If tracking is disabled in your account (as it is by default), this template tag will render to nothing, and //no tracking will occur//, so its presence in your templates does not mean that tracking will be done.
!!Is open tracking reliable?
In short, no. The majority of email clients ave automatic loading of images disabled by default, and that applies to the image that's used for tracking the open. Some email clients, gmail in particular, deliberately try to prevent this kind of tracking, by doing things like pre-fetching images before the user has opened them, making it look like very large numbers of people opened your messages, even though only a few might have (thus destroying any statistical value it might have provided), or blocking any image that has dimensions of 1x1 pixels.
Just as for click tracking, we only attempt to track opens for subscribers that have given their explicit consent. Open tracking is not normally affected by Do Not Track because that is not usually implemented in email client programs. Please refer to the tracking matrix in our [[privacy article|Data Protection & Privacy]] for exactly how our various privacy controls interact.
There is another factor that comes into play if the recipient has images disabled: if we receive a click from a message that we do not already have an opening recorded for, we will record an open event (just one) as well, as it's not possible for a click to happen from a message that was never opened – even with images turned off. If you have done this, the usual symptom is that number of reported clicks and opens will typically be very similar, whereas you would normally expect opens to be significantly higher than clicks.
We do not attempt to support tracking opening of plain-text messages, because obviously they don't support images. Some mailing companies claim that it's possible to do this – it's not; they're lying! We do however provide an //estimate// of the number of users that have opened your plain-text messages by a simple calculation – we take the ratio of opens to clicks (for recipients with images enabled), and apply the same ratio to plain-text message //clicks//, and you'll see that value on our reports.
<!--{{{-->
<div class='header' role='banner'>
<a href="https://info.smartmessages.net/"><img src="https://www.smartmessages.net/img/smartmessages-logo-lt.svg" width="400" alt="Smartmessages logo" style="float:right;margin:4px 4px 0 0;"></a>
<div class='headerShadow'>
<span class='siteTitle' refresh='content' tiddler='SiteTitle'></span>
<span class='siteSubtitle' refresh='content' tiddler='SiteSubtitle'></span>
</div>
<div class='headerForeground'>
<span class='siteTitle' refresh='content' tiddler='SiteTitle'></span>
<span class='siteSubtitle' refresh='content' tiddler='SiteSubtitle'></span>
</div>
</div>
<div id='mainMenu' role='navigation' refresh='content' tiddler='MainMenu'></div>
<div id='sidebar'>
<div id='sidebarOptions' role='navigation' refresh='content' tiddler='SideBarOptions'></div>
<div id='sidebarTabs' role='complementary' refresh='content' force='true' tiddler='SideBarTabs'></div>
</div>
<div id='displayArea' role='main'>
<div id='messageArea'></div>
<div id='tiddlerDisplay'></div>
</div>
<!--}}}-->
Smartmessages is driven via prepaid credits: one credit is one sent message. There are two way of buying your sending credits:
!!Monthly subscription
This provides you with a block of sending credits every month. You will automatically be charged for each month via your credit card. These credits expire after one month, and unused credits do not roll over to the next month. This is ideal if you have regular, predictable mailing patterns.
!!Manual credit purchase
You can buy a block of sending credits that expire after one year. Credits bought this way are slightly more expensive, but are more flexible, result in less wastage, and are ideal if you are running multiple accounts or have a lot of variation in your sending volume.
It's possible to combine these two approaches – use a monthly subscription for your regular mailings, and buy some extra credits for occasional bigger campaigns without needing to upgrade your monthly subscription, or to bridge the difference between subscription plans.
When you send, the system always uses the credits that expire soonest first.
Those with more complex needs, large lists (> 100,000) or those who prefer alternative payment arrangements (such as monthly/quarterly invoice) should [[contact us|ContactUs]].
!How to buy credits?
Click on the "Account" tab:
[IMG[images/account1.png]]
Click on the "Buy Smartmessages.net services" tab to see our subscription plans and credit purchase options:
[IMG[images/smtab1.png]]
When choosing your subscription level, bear in mind [[what the account limits mean|Account limits and quotas]].
At present we do not have an online payment system, and we like to know who our customers are, so please [[contact us|ContactUs]] to get your payments set up.
Phishing attempts to trick users into revealing personal and financial details, often by making web sites that pretend to be sites such as eBay, Paypal and banks, but it can occur for any site that typically asks for personal details. These usually take the form of email messages saying your account has had some kind of problem and that you should log in to the site and update your password; the link they provide will take you to a site that looks like your bank's normal login page, but is actually a fake just looking to steal your passwords. This is clearly a bad thing.
Smartmessages includes support for anti-phishing measures. We provide an opportunity for our customers to include a link back to us (on the account settings page), and we use that link wherever we ask for a subscriber's details, so tey can check that we are legitimately acting for a customer, and not attempting to obtain data for nefarious purposes.
To be safe from phishing, you should check that email messages really come from where they say they do, and that any domain name (the 'example.com' part of 'user@example.com') used in an email is the same as the anti-phishing page our customer has posted. We also recommend tha you use and email provider that supports [[SPF]] and [[DKIM|DKIM and DomainKeys]] checks against incoming mail.
!!Phishing links
One common feature of phishing emails is the use of links which pretend to go to somewhere you may want, but actually go elsewhere. For example they may invite you to log in to somewhere common, say Facebook, and provide a link to a page that looks like a Facebook login page, which fails to log you in, but by then you've given them your ID and password...
Unfortunately it's quite easy to do this by accident. If you create a link in your HTML that looks like this:
{{{
<a href="http://www.example.com/">http://www.example.com/</a>
}}}
That's innocuous as it stands, however, because we add redirects in order to implement link tracking, it is dynamically rewritten to something like:
{{{
<a href="http://smm.im/w/1obySedyob56cN0N1jGjiC3/http%3A%2F%2Fwww.example.com%2F">http://www.example.com/</a>
}}}
and now we have the text of the link looking like one URL, but the link going somewhere else, i.e. something that could be considered a possible phishing attempt. When you're creating templates, links like this will be warned about in the Link report available in the template editor.
There are two simple workarounds for this:
* ''Don't use ~URLs as link text'' – they are not really intended to be human-readable, and unless your audience are web developers, you're not telling them anything they want to know.
* Use the Smartmessages {{{nosmtracking}}} attribute to suppress link rewriting, as described in our [[Link Tracking]] documentation.
We provide a simple placeholder image generator that is useful for filling out templates without needing to create images of the right size. The generated images are simple blocks of solid colour – by default the standard smartmessages colours of dark grey with yellow text. To use a placeholder, just build image tags referring to it like this:
{{{
<img src="/placeholder.php?size=240x160" width="240" height="160" alt="Product image 1">
}}}
That will render to this when previewed:
[IMG[https://www.smartmessages.net/placeholder.php?size=240x160]]
!!Additional options
While these are just placeholders and don't have any real need to look especially good, there are some additional options available:
|{{{bg}}}|This parameter sets the background colour used in the image. It will accept a standard ~CSS-style 3 or 6-digit hex code without a leading hash character, for example {{{a25}}} is a dark pink.|
|{{{fg}}}|This parameter sets the foreground colour used for the text in the image. The format is just as for the {{{bg}}} parameter.|
|{{{text}}}|By default the image displays the image dimensions, which is useful as it's what you want to know when creating real images for your template, but you may want to give it a more meaningful name. This can contain any basic text (no Emoji in here!), and the value must be ~URL-encoded.|
So, using these additional parameters, I might build a different placeholder like this:
{{{
<img src="/placeholder.php?size=240x160&fg=fff&bg=a25&text=Product%20image%201" width="240" height="160" alt="Product image 1">
}}}
Which will render to:
[IMG[https://www.smartmessages.net/placeholder.php?size=240x160&fg=fff&bg=a25&text=Product%20image%201]]
A "pre-header" is a jargon term for a small piece of text that appears at the very start of your message, before any main header or content section. It is interesting because quite a few significant clients (notably Apple Mail, iOS mail, Gmail and Outlook.com) display the first bit of the message in addition to your subject line as part of a kind of mini-preview of each message. HTML tags are ignored, only the actual text is used. By default this is often something like 'if you can't see this message, open this link in your browser', or 'click here to unsubscribe'. Neither of those are especially friendly or useful at this point so it's common to place some additional text up front (the pre-header) so that it's used as the preview. You might think this may make a mess of your layout, but fortunately this text is still displayed in the preview even if it is hidden using CSS. Smartmessages has a built-in tag to help you create preheaders; use it like this:
{{{
[[preheader]]This week's hints and tips from your favourite supplier.[[/preheader]]
}}}
You can add one of these manually or by picking the pre-header snippet from the template snippets list in the mailshot editor. It should be the very first text content in your template.
!Automating pre-header generation
A good way of making your pre-header generate itself automatically (so you don't have to update it every time you send a mailshot) is to use our {{{[[toc]]}}} table of contents tag, like this:
{{{
[[preheader]][[toc start=1 levels=1 flat=true]][[/preheader]]
}}}
This will extract all {{{h1}}} headers with ids in your message and use them as a pre-header.
See the [[template guide|TemplateGuide]] for more details about the {{{[[preheader]]}}} and {{{[[toc]]}}} tags.
RSS stands for [[Really Simple Syndication|http://en.wikipedia.org/wiki/Rss]], which is a micro-publishing mechanism for web sites and other content generating sources. RSS is also used as a general term covering the common RSS 1.0, 2.0 and [[Atom|http://en.wikipedia.org/wiki/Atom_(standard)]] publishing standards.
An RSS feed generally contains some information about the feed itself, such as its title and where it's come from, and a collection of items constituting the feed content, usually news stories or blog posts, along with their titles, publishing date, author, category, and a link to the source of the item. They may contain other metadata elements too, but those are the common ones. The content elements may contain complete content (known as a "full feed") or just a summary or introductory paragraph.
Many people like using RSS feeds as they are typically free of ads, provide clutter-free offline reading (ideal for mobile use), and allow the reader (rather than the web site owner) to decide how they are presented. An RSS reader application will manage multiple feeds, group them into categories and update them regularly, and such functionality is often integrated into browsers (as it is in Internet Explorer, Safari, Opera and others). The usual pattern is that a feed is downloaded, summaries are read, and links to full content (e.g. the original blog post) are followed.
Most content management systems and blogs (for example Wordpress) have the ability to publish RSS feeds of their content which may be consumed by anyone that's interested. A request for an RSS feed is often accompanied by additional parameters that might allow the consumer to specify a date range, a maximum number of items to return, one or more category selections, summarised or full content and so on. As an example, [[this news page at the BBC|http://www.bbc.co.uk/news/]] is also available as [[an RSS feed|http://feeds.bbci.co.uk/news/rss.xml]].
!Why use RSS?
The upshot of all this is that it's possible to create programs that consume the feeds and repurpose them – so you might pull the top 5 stories from your company blog and use them to populate your monthly newsletter in Smartmessages, saving you a lot of copy and paste in the production of your newsletter!
!Using RSS in Smartmessages
Smartmessages supports RSS feeds in [[templates|TemplateGuide]] via two different template function tags called {{{[[rss]]}}} and {{{[[simplerss]]}}}. Both of these render content from an external RSS source into your template, and differ in the amount of control and complexity they provide.
To keep sending performance high, Smartmessages caches fetched RSS feeds for 5 minutes, so it's a good idea to schedule your send with a delay longer than that to be sure that it picks up your latest posts.
Smartmessages tracks clicks on links embedded in RSS feeds, just as for any other content, so clicks on RSS links will appear in your reports.
!!{{{simplerss}}}
This is a straightforward function tag that renders items from an RSS feed with minimal configuration using preset layouts. If you want more control, use the {{{rss}}} tag described below.
|!Parameter |!Purpose |!Default |
| {{{url}}} |The URL of the feed||
| {{{start}}} |The story number to start from (1-25, feed contents permitting)| {{{1}}} |
| {{{items}}} |The number of items to fetch from the feed (1-25, feed contents permitting)| {{{5}}} |
| {{{wordlimit}}} |Number of words to limit each story to| No limit |
| {{{output}}} |The name of a preset content layout| {{{full}}} |
| {{{more}}} |The text to use for "Read more" links| {{{"Read more"}}} |
The {{{url}}} is simply the source URL of the feed, typically found on blog pages in the meta tags.
{{{start}}} is useful if you want to render parts of the same feed more than once in the same message, for example you might want the top 3 stories at the start, then some custom content, then stories 4-6 following it, and you could do that with two {{{simplerss}}} tags with different {{{start}}} values. If you specify a value for {{{start}}}, make sure that it's smaller than the number of stories actually available from your feed, otherwise you may find it renders to nothing.
The {{{output}}} parameter determines which of several preset formats you'd like to use for displaying feed content. The options available are: {{{full}}}, {{{noshare}}}, {{{headlines}}}, {{{list}}}, {{{linear}}} and {{{plain}}}.
The {{{full}}} option looks much like the example template used in the {{{rss}}} tag below:
[IMG[images/simplerss1.png]]
{{{noshare}}} is the same as {{{full}}}, but without social sharing buttons:
[IMG[images/simplerss2.png]]
{{{headlines}}} is a simple vertical list of linked titles:
[IMG[images/simplerss3.png]]
{{{list}}} is similar to {{{headlines}}} but uses a bulleted list:
[IMG[images/simplerss4.png]]
{{{linear}}} is linked titles in one line, separated by pipe ({{{|}}}) characters:
[IMG[images/simplerss5.png]]
{{{plain}}} is simple text titles followed by a URL, suitable for plain-text templates.
{{{2column}}} is a 2-column responsive table-based responsive layout that collapses to a single column on small screens. It uses the Zurb Foundation for Emails 2.0 styles, so it works well with the ~ZF2 templates provided. It will automatically add empty cells in case your {{{items}}} value is not disivisible by your column count – so if you ask for 4 stories in a 3-column layout, you will get 1 row of 3 items and 1 row of 1 item and two blank cells.
[IMG[images/simplerss2column.png]]
{{{3column}}} The same as {{{2column}}}, but using 3 columns.
[IMG[images/simplerss3column.png]]
{{{4column}}} The same as {{{2column}}}, but using 4 columns, and collapses to 2 columns on small screens.
[IMG[images/simplerss4column.png]]
See the notes in the {{{rss}}} tag for info on the {{{wordlimit}}} parameter.
The {{{full}}} and {{{noshare}}} layouts will include a link and appropriate icon (see the {{{mimeicon}}} tag) for any enclosure (for podcasts) and a link to a comments page if it is provided in the feed.
!!!Example
{{{
[[simplerss url="http://feeds.bbci.co.uk/news/rss.xml" items=3 output="headlines"]]
}}}
!!{{{rss}}}
This tag that gives you far more power and control over the formatting of your RSS feed layout and content than the {{{simplerss}}} tag, but at the expense of much greater complexity. {{{[[rss]]}}} is a block tag (much like {{{if}}}) that also expects a matching closing {{{[[/rss]]}}} tag.
|!Parameter |!Purpose |!Default |
| {{{url}}} |The URL of the feed||
| {{{start}}} |The story number to start from (1-25, feed contents permitting)| {{{1}}}|
| {{{items}}} |The number of items to fetch from the feed (1-25, feed contents permitting)| {{{5}}}|
| {{{wordlimit}}} |Number if words to limit each story to.|No limit|
{{{start}}} is useful if you want to render parts of the same feed more than once in the same message, for example you might want the top 3 stories at the start, then some custom content, then stories 4-6 following it, and you could do that with two {{{rss}}} tags with different {{{start}}} values. If you specify a value for {{{start}}}, make sure that it's smaller than the number of stories actually available from your feed, otherwise you may find it renders to nothing.
The {{{wordlimit}}} option is used to limit the size of content sections of stories in a feed (in {{{[[$rssitem.content]]}}} elements) – some "full feed" feeds just provide too much content, so this lets you truncate stories to a manageable length. We recommend starting with 50 as a minimum as it includes HTML markup in the word count; HTML filters will tidy up unclosed tags that are left open by this process. Items in the {{{full}}}, {{{noshare}}} and multi-column layouts are given unique element ~IDs so that they can be included in tables of contents generated using the Smartmessages {{{toc}}} tag.
!Variables
Within the tag, two array variables are defined:
|!Variable | !Element |!Purpose |
| {{{$rss}}} ||The feed itself|
|| {{{title}}} |The title of the feed|
|| {{{url}}} |The URL of the feed|
|| {{{description}}} |A description of the feed|
|| {{{itemcount}}} |The number of items provided by the feed|
| {{{$rssitem}}} ||Repeatedly evaluated to contain each item in the feed|
|| {{{title}}} |The item title|
|| {{{url}}} |The URL of the article's page|
|| {{{content}}} |The item contents – usually includes HTML markup, so be sure to include the {{{nofilter}}} modifier after it.|
|| {{{content_plain}}} |The item contents as plain text with HTML markup removed|
|| {{{description}}} |A short description of the item; may be empty|
|| {{{commenturl}}} |A URL pointing to a comments page about this item|
|| {{{published}}} |A unix timestamp of the publication date and time|
|| {{{updated}}} |A unix timestamp of the most recent update date and time|
|| {{{authorname}}} |The name of the item's author|
|| {{{authoremail}}} |The email address of the item's author|
|| {{{authorurl}}} |A URL referencing the item's author|
|| {{{imageurl}}} |A URL of a representative image for the item, if any|
|| {{{image}}} |An HTML {{{img}}} tag using the URL of the representative image for the item, if any. Remember to use the {{{nofilter}}} modifier to permit HTML.|
|| {{{category}}} |A category string for the item, e.g. 'news', 'science', 'recipes'|
|| {{{enclosureurl}}} |The URL of an attachment, if any|
|| {{{enclosuretype}}} |The MIME type of any attachment e.g. {{{audio/mp3}}} (use the {{{mimeicon}}} function to convert this into an icon)|
|| {{{enclosurelength}}} |The size of the attachment in bytes|
|| {{{first}}} |Whether this is the first item in the feed|
|| {{{last}}} |Whether this is the last item in the feed|
|| {{{index}}} |The number of the item within the feed (first item has index 0)|
It's important to realise that RSS feeds vary enormously, and many of these properties may be unpopulated (empty), though we have tried to consolidate the different feed formats (for example Atom feeds typically don't include a category, RSS 1.0 feeds don't include an update date), so if you're using an element, it's important to test it with your intended feed to make sure it looks right. Most important of these consolidations is that we always make sure that {{{[[$rssitem.content]]}}} contains the item contents, even though the feed may place it in summary or description fields internally. Content is heavily filtered for security (so scripts and other problematic content is removed), but this means that it's safe to display the HTML content provided by the feed.
The {{{image}}} and {{{imageurl}}} properties will use the same URL as an enclosure if one is present and is an image type. Failing that, it will search the item's {{{content}}} and use the URL of the first image it finds, if any. The {{{image}}} tag includes an inline style attribute containing {{{width: 100%; height: auto}}}. This means that you should control the size of images by adjusting the size of the containing element, and the image will expand to fill the width of it while maintaiing aspect ratio. This works especially well for responsive templates.
!!!Example
{{{
[[rss url="http://feeds.bbci.co.uk/news/rss.xml" items=5 wordlimit=100]]
[[if $rssitem.first]]<h2 id="rsstitle"><a href="[[$rss.url]]">[[$rss.title]]</a></h2>[[/if]]
<div class="rssitem" id="rssitem[[$rssitem.index]]">
<h3>[[$rssitem.title]]</h3>
<p class="rssbyline">[[$rssitem.published|date_format:"%b %e %Y %H:%M"]] | [[$rssitem.authorname]]</p>
[[$rssitem.content nofilter]]
<p><a href="[[$rssitem.url]]">Read more</a></p>
[[facebook_like url=$rssitem.url]] [[googleplus_share url=$rssitem.url]] [[twitter_share url=$rssitem.url]] [[linkedin_share url=$rssitem.url]]
</div>
[[/rss]]
}}}
This template is rendered in a loop between the opening and closing tags, changing the contents of the {{{$rssitem}}} array each time around. In this example you can see it's using the {{{$rssitem.first}}} property to display the title of the feed the first time around the loop. Although the filtered HTML content is safe to use, it is still escaped by default, so you need to apply the {{{nofilter}}} option when displaying {{{$rssitem.content}}} to allow the HTML to pass through to the template. The {{{$rssitem.published}}} timestamp is using the {{{date_format}}} modifier to turn the unfriendly unix timestamp into a more presentable form. Unique ~IDs are assigned to the item titles so that they can be picked up by the {{{toc}}} table of contents tag. The social sharing tags have their default ~URLs overridden to use the url of each story instead of the mailshot web version.
Note that you may need to place Smartmessages tags in places that are not valid in HTML, and this may cause problems in the WYSIWYG editor, which enforces valid HTML. You can work around this by using HTML comments, for example, in this example which implements a ~ZF2-styled multi-column RSS layout, much like the {{{simplerss}}} {{{2column}}} layout does. Here we need to hide Smartmessages tags from the editor because we need template tags to be placed between {{{<tbody>}}} and {{{<tr>}}} tags, which is not valid HTML, but it's OK if we wrap them in HTML comments:
{{{
<!-- [[$columns = 2]] -->
<table class="row">
<tbody><!-- [[rss url="http://feeds.bbci.co.uk/news/technology/rss.xml" items=$columns*2]] --><!-- [[if $rssitem.index%$columns == 0]] -->
<tr><!--[[/if]] -->
<th class="rssitem small-12 large-6 columns[[if $rssitem.index%$columns == 0]] first[[elseif $rssitem.index%$columns == $columns-1]] last[[/if]]" id="rssitem[[$rssitem.index]]">
<h5>[[$rssitem.title]]</h5>
[[$rssitem.content nofilter]]
<p>[[$rssitem.published|date_format:"%b %e %Y %H:%M"]] <a href="[[$rssitem.url]]">Read more</a></p>
</th>
<!-- [[if $rssitem.index%$columns == $columns-1]] -->
<th class="expander"> </th>
</tr>
<!--[[/if]] --><!-- [[/rss]] -->
</tbody>
</table>
}}}
You can place multiple RSS feeds in your templates using different ~URLs and item counts in each tag.
The quickest way to send a new mailshot that's similar to one you've done before is to make a copy and edit it, for example to send this month's newsletter, you might copy last month's and edit it. This can save quite a bit of work.
Choose the mailings tab: [IMG[images/mailings.gif]]
Click the copy button for the mailing you wish to use as the basis for next mailing. [IMG[images/mailings2.gif]]
Click the Edit button for the new mailshot.[IMG[images/edit.gif]]
This will take you to the send page populated with the details from the original mailing.
Every completed mailshot has a report. Recent non-test mailings are listed on the home page, so you can quickly see what's been happening with yotu latest mailings. For everything else, click on the ''mailings'' tab, then click on a ''report'' button to see results.
On the mailings page you can also download a report for a whole campaign, rather than just a single mailshot. These are provided as Excel spreadsheets with a sheet for each mailshot and a summary page on the front. All the sheets use named ranges so it's easy for you to customise further.
[IMG[images/mailings3.gif]]
The requirement for verified, explicit opt-in consent for marketing is a slightly grey area. If you obtain personal data on individuals as part of a business transaction, you may contact them for marketing purposes, but ''only'' if they were asked to opt-in to marketing at the time of the transaction, and if that consent was compliant with //current// requirements of the [[GDPR]] (which it may have been if your systems were compliant with earlier data protection legislation). Of course we were not party to that transaction, so all subscriptions obtained through Smartmessages (or any other mailing service) //must// be handled on the basis of consent, not an ambiguous "legitimate interest" basis. You can read a good article on this situation [[here|http://privacylawblog.fieldfisher.com/2017/re-consenting-to-marketing-under-gdpr/]]. GDPR is not the end of the story though – you have no control over where your subscribers sign up from, and the data protection law applicable to them depends on where //they// are, not you or us, so it's prudent to comply with the strictest laws that may be applicable. For example in Canada strict opt-in consent is //always// required for marketing purposes; there was a 3-year transitional legitimate interest / implied consent option, but that expired in July 2017.
The net result is that if you have imported a mailing list by uploading a uploaded file, or you have subscribers that signed up prior to our introduction of enforced double-opt-in in 2006(!), you will lack verification data for those subscriptions, in contrast to those that have signed up using our subscription processes. Alongside the [[GDPR]], The Electronic Privacy Regulation ("ePR") requires opt-in consent for marketing purposes, and for that to have any legal standing it must be verifiable, and the only way to obtain that is using double-opt-in (see our [[data protection|Data Protection & Privacy]] article for more info). So if you have subscribers in this category, how do you go about obtaining verification?
!!Providing reverification links
Smartmessages provides a template tag in the form of {{{[[$subscriber.reverification_url]]}}}. This is a specially crafted URL that acts like the first half of a double-opt-in verification, effectively turning every message in your mailshot into an opportunity for subscribers to complete a double-opt-in. Generally you will only want to offer that option if the subscriber has not already verified their subscription, and you only want to display the option if the version of the message they are looking at is personalised for them (e.g. not a generic "web version"). That means we need to wrap this link in a condition so it's only shown in those situations. A simple example would be this:
{{{
[[if $message.ispersonal and $subscription.verified != 'yes']]
<p>Do you want to continue to receive messages from us? Click the button to let us know! [[button url=$subscription.reverification_url text="Yes please!"]]</p>
[[/if]]
}}}
Here we've used our {{{[[button]]}}} tag to create a nice-looking button that uses the URL, but you could create a regular link in a similar way:
{{{
[[if $message.ispersonal and $subscription.verified != 'yes']]
<p>Do you want to continue to receive messages from us? <a href="[[$subscription.reverification_url]]">Yes please!</a></p>
[[/if]]
}}}
Clicking this link will result in the subscriber being sent a double-opt-in verification request to which they will need to respond – effectively exactly what they would have needed to do if they had visited your mailing list subscription page and submitted their address. We need to treat the request this way (and not simply confirm it on the basis of the link) because we need to retain a copy of the confirmation message and to protect against false verifications being completed by mail scanners (which often visit every link in a message as protection against malware).
SPF is the [[Sender Policy Framework|http://www.openspf.org/]], a mechanism used for preventing forgery of from addresses in email, and because of its strength in proving you are who you say you are, improves deliverability as filters are less likely to think that you are sending spam or phishing emails (and conversely, if you are sending spam, they can block you more effectively). It's an increasingly important weapon in the war against spam, it's used by most of the big email providers (AOL, Hotmail/MSN/Windows Live, Yahoo!, ~GMail, etc) and we recommend full support for it.
!!How does it work?
When you send a message through Smartmessages, it will be sent by one of our mail servers. Normally, there's nothing to confirm that we're not just pretending to send legitimate messages from you, and because of that, servers receiving these messages may treat them with suspicion. You can fix this by naming us as a source of email for your domain in an SPF record, which is part of your domain name (DNS) setup. Read the [[OpenSPF site|http://www.openspf.org/]] for info on how to do that – the key thing is that you should add us to your SPF record, which will allow us to send mail from your domain.
!!The technical bit
Read the [[OpenSPF|http://www.openspf.org/]] docs and/or use their wizard to create an appropriate SPF string, then insert it into your DNS as a TXT record.
A fail-safe SPF record that includes us is:
{{{
v=spf1 a mx include:smartmessages.net ?all
}}}
This translates to: //Explicitly allow sending from this domain, its mail servers and Smartmessages. For everyone else, give a neutral response.// Ideally you should aim for a {{{-all}}} (default to 'fail' rather than 'neutral' status), but don't set that until you're sure you have all your mail sources covered, and even then it may cause issues with messages sent via relay servers that do not implement SRS. //If you're using [[DMARC|http://www.dmarc.org/]], don't use {{{-all}}}, use {{{~all}}}, which delegates the PASS/FAIL decision to DMARC//.
Once you've set it up, you can check it (and everything else in your DNS) is working using a service like [[dnsreport|http://dnsreport.com/]]. If you have a Unix/Linux/~MacOS X command line handy, you can try {{{dig txt example.com}}} to check that your DNS is publishing your record correctly.
You can do SPF lookups [[here|http://www.openspf.org/Why?showform=1]]. Enter one of our IP addresses (e.g. {{{93.93.128.140}}}) and your proposed from address. Ideally you want a 'Pass' result, though 'Neutral' will work. If you get a 'Fail' or 'Softfail' response, we will not be able to send from that address reliably for you.
If you want to be an especially good citizen in your SPF records, it's nice to provide IP addresses rather than hostnames as it saves the receiving mail server a DNS lookup. For example instead of using {{{a}}} or {{{a:www.example.com}}}, specify the actual IP, like {{{ip4:123.123.123.123}}}. The terms in an SPF record are evaluated left to right, so put the most likely matches first. You can do similar things for your MX record, though if you use a commercial incoming mail service like messagelabs, we suggest you stick with a regular {{{mx}}} rather than enumerating their ~IPs. They may also have an SPF include option you can use, so check their support pages.
We recommend that you don't enumerate our server ~IPs in your SPF, but use the include delegation we suggest as then we'll retain the ability to reconfigure our own servers without having to bother you with updates. Our own SPF uses a {{{-all}}} default, so we don't represent a back-door to neutral responses.
!!Are there any downsides?
One in particular: If you commonly send email through your ISP or web mail provider using your own domain as the from address (i.e. you are in the habit of forging your own address!), you have three options:
#Use the '?all' default action (which doesn't do anything for spam prevention)
#Include the ~IPs of your ~ISPs mail servers (they should be able to supply them, but it means that anyone else at your ISP can forge mail from you)
#Alter your sending settings so you only send through your own mail servers (the most effective, but least flexible way). If your ISP blocks or redirects SMTP traffic on port 25, you may be able to get to your mail server using a submission port which is typically on port 587 and tends not to get blocked; the submission protocol usually stipulates that you use both authentication and TLS encryption too, so it's a good security measure.
Another downside is that even if you go to the effort of implementing SPF, but can't get as far as a {{{-all}}} default policy, it's not going to gain you very much since even the most brazen forger will only merit a {{{SOFTFAIL}}} response.
!!Google's Blacklisting Policy
Google has a very simple approach to SPF failures: messages are rejected, and they automatically add you to the [[CBL blacklist|http://cbl.abuseat.org/]], which is used by hundreds of ~ISPs. So a single message with an incorrect SPF setup could get you (and us) blacklisted from many ~ISPs. We plan to enhance our send-time SPF checks to ensure you can't send if your from address will cause an SPF failure.
!!What about ~SenderID?
[[SenderID|http://www.microsoft.com/mscorp/safety/technologies/senderid/default.mspx]] is a Microsoft-backed extension of SPF. It has some [[well documented pitfalls|http://www.openspf.org/SPF_vs_Sender_ID]] and is generally disliked, and even Microsoft no longer uses it itself on their email sites (Hotmail, live.com, outlook.com, office365). If you need it for some compliance reason, the most straightforward way to implement ~SenderID is to set up your SPF record and then delegate to it. This way you will only have one record to maintain (your SPF) to identify your legitimate mail sources. To do this, create another TXT record containing this text:
{{{
spf2.0/pra ?all
}}}
And that's it. Having done this, you should [[register your use of SenderID|https://support.msn.com/eform.aspx?productKey=senderid&page=support_senderid_options_form_byemail&ct=eformts]] on Microsoft's site to ensure they use it.
!!What about ~DomainKeys and DKIM?
While SPF helps to increase trust that a message's //origin// is where it says it is, DKIM and Domainkeys serve to show that a message's //content// has not been altered in transit, so the two go hand-in-hand. The way it works is fairly complex (using public-key cryptographic signatures), however the practicalities are quite straightforward. If you're already altering your DNS to add our SPF, then we thoroughly recommend that you set up DKIM as well. [[Read our guide|DKIM and DomainKeys]] on what it means and how to do it.
!!Example of a forgery rejection
Someone on the Turkish ~MarsNet DSL service attempted to send a message that claimed it was sent from our own mail server. Not surprisingly, when an SPF check was done by a Turk Telecom mail server (thank you Turk Telecom!), the message was rejected because our SPF record correctly identified it as a forgery. You can see that amongst the headers is a link to a page which will explain why the message was rejected. This is absolutely what SPF is intended to achieve, and here you can see it working perfectly.
{{{
This is an informative message sent by mail.atamedya.com.
The server was not able to deliver your email message to the following addresses:
<sales@synchromedia.co.uk> (mail.synchromedia.co.uk: 550 See http://spf.pobox.com/why.html?sender=postmaster@synchromedia.co.uk&ip=77.92.158.139&receiver=mail.synchromedia.co.uk (#5.7.1))Reporting-MTA: dns; mail.atamedya.com
Arrival-Date: Thu, 16 Jul 2009 12:01:44 +0300
Final-Recipient: rfc822;sales@synchromedia.co.uk
Action: failed
Status: 5.1.1
Remote-MTA: mail.synchromedia.co.uk
Diagnostic-Code: SMTP; 550 See http://spf.pobox.com/why.html?sender=postmaster@synchromedia.co.uk&ip=77.92.158.139&receiver=mail.synchromedia.co.uk (#5.7.1)
Received: from synchromedia.co.uk ([81.215.222.134])
by mail.atamedya.com (Kerio MailServer 6.1.4)
for sales@synchromedia.co.uk;
Thu, 16 Jul 2009 12:01:42 +0300
From: "Post Office" <postmaster@synchromedia.co.uk>
To: sales@synchromedia.co.uk
Subject:
Date: Thu, 16 Jul 2009 12:01:11 +0300
MIME-Version: 1.0
Content-Type: multipart/mixed;
boundary="----=_NextPart_000_0014_D23B030D.A4D8B533"
X-Priority: 3
X-MSMail-Priority: Normal
X-Mailer: Microsoft Outlook Express 6.00.2600.0000
X-MIMEOLE: Produced By Microsoft MimeOLE V6.00.2600.0000
}}}
We are very aware that we are holding your precious data. Here are some of the ways we aim to keep your data safe – if you're looking at any other ~ESPs, you should check they provide all of these things too. You'll often find our staff speaking on security topics at technical conferences.
!!TLS encryption
We use secure TLS (SSL) connections whenever you're viewing our site (look out for a little padlock in your browser) – this means that ''all'' ~URLs, data (e.g. your lists), pages, cookies, etc are safely protected from anyone eavesdropping on the connection between us. Any site that doesn't do this is bordering on breaking the data protection act (though not quite breaking it, yet). Our mail servers use TLS too, so the messages we send out are also safe from prying eyes while in transit, so long as the recipients mail servers support it too. Our TLS configuration is state of the art, utilising all available security measures including [[HSTS|https://en.wikipedia.org/wiki/HTTP_Strict_Transport_Security]], [[HPKP|https://en.wikipedia.org/wiki/HTTP_Public_Key_Pinning]], [[CAA records|https://en.wikipedia.org/wiki/DNS_Certification_Authority_Authorization]], [[OCSP certificate stapling|https://en.wikipedia.org/wiki/OCSP_stapling]], [[must-staple|https://en.wikipedia.org/wiki/Online_Certificate_Status_Protocol]], modern ciphers (including ~ChaCha20/Poly1305 for better mobile performance), RSA and ECC certificates, large DH parameters, etc. Our domains are in [[HSTS preload lists|https://hstspreload.org/?domain=www.smartmessages.net]], so we avoid the TOFU (Trust On First Use) security hole, and encryption will be used from the very first request.
You don't have to take our word for it – feel free to test our configuration yourself using [[Qualys SSL Labs' testing service|https://www.ssllabs.com/ssltest/analyze.html?d=www.smartmessages.net]] a reputable third party testing service; we aim to maintain (it's a moving target!) a full ''A+ grade''.
[IMG[images/sm_qualys.png]]
!!Security headers
We make a point of enabling security features built into web browsers by setting appropriate HTTP headers. This includes uncompromising {{{Strict-Transport-Security}}} (with preload, subdomains & long expiry), ensuring that our site will //always// be served over a secure connection, or not at all. We also make full use of {{{Public-Key-Pins}}}, {{{X-Content-Type-Options}}}, {{{X-XSS-Protection}}}, {{{X-Frame-Options}}}, {{{Referrer-Policy}}} and {{{Content-Security-Policy}}} HTTP headers. Again, you can check our compliance using [[securityheaders.io's testing service|https://securityheaders.io/?q=https%3A%2F%2Fwww.smartmessages.net%2Flogin.php&followRedirects=on]].
[IMG[images/sm_sechead.png]]
In particular we have an extremely strict Content Security Policy header on the domain that we use for serving images and click tracking (smm.im). This means that even if someone managed to upload some malware (e.g. a Javascript cryptominer) onto our image servers, your browser would refuse to download it.
!!Passwords
Inevitably, we make use of passwords for account holders and subscribers. We store passwords as [[bcrypt hashes|https://en.wikipedia.org/wiki/Bcrypt]] with integrated salts and a large work factor, meaning they are practically impossible to reverse, should anyone manage to obtain a copy of our database (in the style of [[haveibeenpwned.com|https://haveibeenpwned.com]]), and explicitly ''do not'' store passwords in plain-text or using weak hashes such as ~MD5 or ~SHA-1. We follow [[NIST's 2017 guidelines|https://pages.nist.gov/800-63-3/sp800-63b.html]] on passwords, which amount to "make it long", "make it unusual" (rather than complex old-style rules about uppper & lower case, numbers, symbols etc) and permit passwords up to 72 bytes (a limitation of bcrypt), including [[emoji|Emoji]], spaces, and international characters. We use Dropbox' popular [[zxcvbn|https://github.com/dropbox/zxcvbn]] library to help with this, used for both client and server validations. We do not prevent pasting into login forms, and highly recommend using a password manager such as [[1Password|https://1password.com]] or [[EnPass|https://www.enpass.io/]] for generating and storing strong passwords. We do not support social logins ("Log in with Facebook" etc) because it's impossible to use them without compromising privacy. We don't provide enough information to allow user enumeration on our login or password reset forms, employ brute-force protection, and have additional measures to prevent timing side-channel attacks during login attempts.
!!Authenticated callbacks
If you make use of our [[Callbacks]] to keep your data in sync with what happens on our side of things, we authenticate the requests we send you using a strong MAC code, so you can be sure that it's us sending you the data, and that it's not been tampered with in transit, even if you don't use HTTPS (which you should be!).
!!Make no attempt to hide
All our internet host names resolve properly both forwards and backwards, and they change only very rarely (for example when we use a new ISP or add new servers) – we don't try to hide our servers because we don't send spam. [[Our Whois data|https://whois.icann.org/en/lookup?name=smartmessages.net]] is valid and points at a real person. While it isn't necessarily applicable in the EU, verifiable identity is a requirement of ~CAN-SPAM compliance in the US.
!!Firewalls
We use stateful Linux firewalls for all public-facing servers permitting only protocols and ports that are required for the services they run. Between servers in our cluster we only allow access from specific sources.
!!SPF support
All the mail we send in our own name is validated by our [[SPF]] record (which is set as strict as it can be) so recipients can be sure that we sent it, not someone pretending to be us.
!!DKIM support
All the mail we send (both for ourselves and for account holders) is signed with 2048-bit [[DKIM keys|DKIM and DomainKeys]] which guarantee that messages cannot be tampered with in transit, that we are who we say we are, and that we are permitted to send on your behalf (if you set up our keys as we describe). We have some legacy support for older 384- and 1024-bit DKIM signatures but do not encourage their use.
!!Our locations
Our servers are located in London. We host at [[Equinix|http://www.equinix.co.uk/locations/united-kingdom-colocation/london-data-centers/]] Sovereign House and Harbour Exchange data centres in London's docklands, one of the UK's premier hosting locations, featuring clean, reliable power supplies, overspecified air conditioning, heavy physical security (retinal scanners etc). Our hosting provider is [[Mythic Beasts|https://www.mythic-beasts.com/]]. We perform some processing and host various resources (for example, our web site and help pages) on servers in France, hosted by gandi.net in Paris, but this does not involve personal data.
We will never export personal data out of the EU.
!!Our code
We follow best practices when it comes to writing secure code. We have defences against SQL and header injection attacks (about the most common kinds) amongst others, and our servers are always kept up to date with the latest security patches.
We don't run other web apps (e.g. forums, blogs, ~CMSs etc) on our cluster (for example this wiki is not on it), so we're not exposed to security holes in such packages.
!!Admin access
Administrators access our servers over secure shell (SSH) using strong public key encryption and authentication only, and common unauthorised access attempts are logged and used to block further attempts. There are very few people able to access critical back-end systems, reducing the potential for rogue staff members to expose personal data.
!!Viruses, trojans etc
We don't scan outgoing messages because we generate every message from scratch – we never forward anything from others, and we don't allow attachments or ~Javascript in our messages, eliminating the most common infection vectors. For what it's worth, we don't run Windows on desktops or servers, where a large proportion of security threats (Word documents, viruses, malware, ransomware, etc) are found.
!!Backups
We take backups every night, so we guarantee to have a backup of all your data up to that age. Beyond that your data is your responsibility – you can download a copy of your subscriber data from us any time you like. Backups are encrypted and are not kept on publicly accessible systems.
!!Redundancy
Smartmessages runs on a cluster of redundant servers, allowing hot failover should one fail. All critical systems reside on RAID volumes and use redundant power supplies, so we're protected against the most common kinds of hardware failures.
!!Physical security
We host at [[Equinix|http://www.equinix.co.uk/locations/united-kingdom-colocation/london-data-centers/]]'s Sovereign House and Harbour Exchange data centres in London's docklands, one of the UK's premier hosting locations, featuring clean, reliable power supplies, overspecified air conditioning, heavy physical security (retinal scanners etc).
!!But that's not the end of the story...
It's ''your'' data we're trying to keep safe, so you can help too. Implement [[SPF]], [[DKIM|DKIM and DomainKeys]] and [[DMARC]] for your own domain names, and add us to your list of permitted email sources. Make use of our [[anti-phishing|Phishing]] features, especially if you are collecting data from your recipients through any of our services. Make sure you serve everything using TLS encryption too – it's free, and faster than without – we can provide consultancy if you need help with that.
"Send to a friend" is a feature whereby having received a message from us, you feel you might like to forward it to a friend, and rather than using your email program's forward facility, you come to our site and fill in a form that sends your friend a copy of a message. Sounds like a good idea, but it has numerous hidden pitfalls.
!!Our solution
We provide a simple forwarding approach that has none of the downsides of the "traditional" approach: We provide a link that creates an email message in the user's usual email program, pre-populated with a link to the web version of the original message. This way:
* The message is sent directly from the recipient to the friend – we're not involved at all.
* It's instant and very easy to use – no logins, no web forms required
* The friend gets to see your message in full, with none of the original recipient's personalisation, and guaranteed free of any problems introduced by the original recipients own email service or program (many such programs corrupt or "constructively rewrite" forwarded messages).
!!What's wrong with the original way?
* It's very unlikely to be used. When reading an email you want to forward, your first reaction is to use your normal "forward" command, not one built in to the message.
* The person who receives the message effectively receives an unsolicited message from us. That's borderline legal in the UK, but in many countries it's an imprisonable offence (for example in Germany and Spain). Since it is us that is doing the sending, we're not too happy about that.
* For compliance with data protection laws (including in the UK), we have no rights to, and thus can hold no data about the friend that you sent the message to – we must discard everything, so this operation has zero value for collecting leads. Any ESP that offers this service is acting illegally. Several ~ESPs and senders have been successfully sued for this practice, and we don't want to join them.
* Any unsolicited message is much more likely to be reported as spam, which when considered globally is likely to negatively impact the deliverability of ALL of your other mailings, including those for which you have full opt-in permission.
* If we pretend that you are the sender (e.g. by sending from your address) we will be spotted as a fake, your message may well be rejected by any receiver that implements SPF (as we recommend), and you're even more likely to be reported as spam.
* In order to provide a web page where you could do this safely, you would need to log in to our site. If we didn't do this, we would be providing a spam gateway.
* It's not all down to you – we send messages for all kinds of companies, and allowing it for one could reduce the deliverability of ALL those that use Smartmessages, including you.
Does it still sound like a good idea? Even if we did provide this service, the one and only benefit you could possibly derive is a very small increase in the number of people that you know have viewed your message. Say 0.5% of recipients (being generous!) forward the message by this route. Perhaps half of those might arrive unaffected by filters (because of their forged origin), and of those that do, 75% of them might actually be read (the one upside of supposedly being from a friend!). All that effort represents a possible 0.18% increase in opening stats, something that could easily be wiped out by a single spam report.
!!How fast does sending go?
Rates vary because of many factors, but you should expect rates over 500,000 messages/hour for larger mailshots. We are working on improving this all the time. Factors affecting send rates include:
* Size and complexity of your template
* Size of your list
* Activities of other Smartmessages users
* Distribution of recipients (e.g. sending all to one ISP may be slower).
Lists of over about 16,000 recipients will get the highest send rates as over that size mailings can take best advantage of our sending cluster.
Should you have particular performance requirements beyond this, we can add servers to improve throughput at any time.
!!Why wouldn't I want it to go faster?
There is a large negative associated with a high send rate – it may adversely affect your delivery success rate. Many large ~ISPs (Yahoo!, Googlemail, AOL, MSN etc) impose restrictions on how many messages may be sent from one location in a given amount of time, or the frequency with which you send messages to specific users. They don't explicitly tell you that they are doing this, or let you know what their limits are, but you'll find that you'll get increasingly large numbers of bounces with a "4.4.1 Deferred Delivery" code. This code means that they may accept the message at some unspecified time in the future. Our mail server will retry delivery and progressively fall back with longer and longer times until it just gives up, typically after 4-7 days.
There are six steps to the send process:
# Choose your template
# Name your mailshot & choose where it will be saved
# Add extra content if required for the email
# Choose who you are sending it to
# Choose which email address you are sending the email from & also the reply address
# Choose when to send the mailshot
There is also a 'final check' page where all the selected options are presented together for you to check before sending. Once a mailshot has been sent, it has gone, there is no 'undo', so be careful! Our servers go very fast, so hitting pause could still mean that 1000's of emails have been sent, and may not be possible at all on small mailings.
See also [[Continuous mailshots]].
Here are the screens from the system:
[IMG[images/smsend1.gif]]
[IMG[images/smsend2.gif]]
[IMG[images/smsend3.gif]]
[IMG[images/smsend4.gif]]
[IMG[images/smsend5.gif]]
[IMG[images/smsend6.gif]]
[IMG[images/smsend7.gif]]
[IMG[images/smsend8.gif]]
When you log in to Smartmessages, one of the first things you'll see is the setup checklist. These are various things you can set up in your account, and on external services, that will help improve how you appear to your subscribers, and help get your messages delivered to inboxes rather than spam filters. Here's a short description of each item we suggest:
!!Contact details
One sure way to improve your reception is for your subscribers know that messages are from you, and that they can get in touch with you easily. If you fill in your contact details on the settings page, we can make use of that information in many of the places that your subscribers come into contact with your messages and administrative pages (such as unsubscribes).
!!Set up your branding
It's great when your customers remember your name, but for many it's your branding – your colours, styles and logo – that brings more immediate familiarity. Set your colours and fonts on the branding page and you're well on your way to looking like the familiar face your customers know (and hopefully love!).
!!Upload your logo
Very much part of your branding, provide us with a nice logo and we'll use it when your subscribers interact with us,
!!Domain authentication
This is a techie one – your subscribers are far more likely to look favourably on messages from you if they can be sure that they are really from you and not someone pretending to be you. And it's not just your subscribers – the service providers your subscribers use also like such guarantees. If you're unfamiliar with DNS, you may need some help (from us or your local friendly geek) with setting up [[SPF]], [[DKIM|DKIM and DomainKeys]] and [[DMARC]].
!!Google analytics integration
[[Google analytics|GoogleAnalytics]] lets you know where your new leads are coming from. You're free to add your own URL parameters, but we can also do it for you automatically, which is much less hassle.
!!Set up an anti-phishing page.
These days it's not enough to say who you are and that you're acting in good faith – you have to be able to back it up. That's why SPF and DKIM have become so important, but they only apply to the email side of things, and only come into effect //after// someone has signed up. To improve potential subscriber's confidence that you are really you (or more to the point, that we are really acting for you), you can use an [[anti-phishing page|Phishing]]. It's a simple concept – place a page on your own site pointing at us, tell us about it, and we will point at that page on our signup pages so that your new subscribers know we are really acting on your behalf.
!!Social network setup
You can't avid social networking these days – and it's become an important marketing channel in its own right. To help generate automatic links and sharing opportunities for the messages you send, tell us your facebook, twitter, ~LinkedIn and Google+ ~IDs on the settings page and we will use them to help promote you whenever we get the chance.
!!Import a mailing list
This is pretty important step – the best lists are home-grown, but if you've already got one and need to [[import it|UploadLists]], you'll need to massage it into the right format (we're pretty forgiving!) and upload it.
!!Send a mailshot
This is after all, why you are here! Just go to the mailings page and click a 'new mailshot' button.
Hopefully all that will get you off to a good start. Since you're reading this, you now know where our help site is. Do take a look around – there's an enormous amount of info about email marketing here. If you need more help, [[please ask|ContactUs]]!
Help and tips for your Smartmessages.net account
http://wiki.smartmessages.net/
Launched in 2003 and quickly picked up business working with the Telegraph Group, we continue to provided emailing services for them today.
Our systems are based in the Docklands, London, UK
Smartmessages is now a mature service having sent out hundreds of millions of emails for clients, including Ebookers and The Daily Mail.
Smartmessages Technical help wiki – If you have a technical question and the answer isn't here then please contact us and we will anser you and update our wiki.
Smartmessages has support for helping your message get out onto popular social networking sites including Facebook, Twitter, Google+ and ~LinkedIn.
!What can be shared?
Our social networking features are all about your subscribers liking the email they have been sent, rather than your Facebook/~LinkedIn etc pages. Because the email message itself can't be shared directly on the web, the sharing is of the web version of an email. This also prevents any personal data from being exposed. The template tags we offer all point at the web version, and because every web version has a unique URL we can report on them separately, which is the data that you'll see in our social networking reports.
[IMG[images/social.gif]]
If you want to point your subscribers at, for example, your facebook page, do that using a normal link, which will be tracked like any other link in your emails and reported with other clicks, not in the social networking reports.
!How social network sharing works
Here's an example of how facebook's 'like' button works; other networks are similar.
* A user sees something they like that has a Facebook 'like' button on it, which they click.
* Behind the scenes, Facebook receives the click, examines the source URL that the button gives it (which might not be the same page), requests it, and examines the page for additional information.
* A web page opens giving the recipient a chance to add a comment about the item, and also showing a preview of information about the link, which will usually include a title (which is a link), a short excerpt of text, and a preview thumbnail image.
* The recipients optionally fills in a comment, clicks ok.
* The 'like' appears in their timeline and is made visible to all their friends, who look at it and hopefully 'like' it too.
The 'behind the scenes' part here is implemented through something called [[open graph tags|http://ogp.me/]], which is a standard common to many social networking sites, including Facebook, ~LinkedIn and Google+. We take care of all that for you.
After this has happened, we can ask the social networks how many 'likes' have happened for the page in question, and report that figure back to you. The link we present to social networks is that of the generic, non-personalised web preview of your mailshot, so there is no opportunity for leaking your recipients' confidential data.
If you want to target something other than the mailshot preview (for example your own site's home page), you'll need to create your own ~URLs, and you will be limited to using only static content (see notes about appearance below).
!Getting started
First things first: go to your Smartmessages account settings page and make sure the 'Allow open graph tags' option is checked. Open graph tags are added to your templates if they are going to be visible to social networks: they are used to extract information about the page (metadata) that's not available from the URL itself, such as the page title, a preview image for it, where it's from etc.
Next, fill in your Twitter ID – if you don't have one, sign up for one on [[twitter.com|https://twitter.com/]] – and we will use this when creating links to share on twitter, and mentions of your ID will automatically appear in your twitter client (or on the twitter web site).
!Twitter follow
If you want to have people follow you on twitter rather than share a link to one of your emails, fill in your twitter account in account settings and add the function tag {{{[[twitter_follow]]}}} to your template, and we'll generate a standard twitter follow button.
!Adding tags
You need to add links to your templates for the various sharing buttons. These are available in the pop-up menu of insertable fields in the HTML editor. The tags are {{{[[facebook_like]]}}}, {{{[[twitter_share]]}}}, {{{[[googleplus_share]]}}} and {{{[[linkedin_share]]}}}. That's all there is to it!
If you want to use your own graphics or text to build these links, we provide plain ~URLs for these services too. The tags for them are:
{{{[[$mailshot.facebook_staticshareurl]]}}}, {{{[[$mailshot.twitter_staticshareurl]]}}}, {{{[[$mailshot.googleplus_staticshareurl]]}}} and {{{[[$mailshot.linkedin_staticshareurl]]}}}.
!Practical considerations
The standard sharing buttons for social web sites are designed for use on the web, and are not a good fit for email, in particular they often use javascript and iframes, neither of which work //at all// in email. Fortunately there are simplified buttons for most of the networks where the most important sharing options are possible via nothing more than a normal HTML link. A complication is that you want to use the simplified buttons in email, but the enhanced ones when viewing a web page. This split functionality is built-in to the buttons we provide, but you'll find they don't quite look the same – the web versions often include additional dynamic information, such as the number of people that have already clicked, and the names of a recipient's friends that have clicked them, see below for examples.
In general we have selected the simplest, smallest display option available for each network, though we do include click counts if they are available as they are good encouragement. We have no control over how dynamic versions appear (and they may change at any time), so we suggest you place them in wrapper divs away from your main content, and don't get hung up on pixel perfection since we have no control over it!
!Button appearance
There are three different contexts that sharing buttons can appear in:
#When previewing a template in the template editor
#When previewing a mailshot (sent or unsent)
#In a sent email message
Cases 1 and 2 both occur in your web browser, so they make use of dynamic buttons. A problem with case 1 is that the URL that you 'share' is not visible to the outside world (it requires that the requester (in this case Facebook etc) has access to your Smartmessages account, which they don't); this means that the buttons may not work as expected in this view. Case 2 will work fine since the mailshot preview is publicly visible (it's the same thing as the web version your emails link to), and will display the dynamic versions of the buttons. Case 3 is how your recipients will typically see the buttons, which is the simplified versions mentioned above, which are small images with HTML links. Here are examples of how they appear in email:
* Facebook: [IMG[https://www.smartmessages.net/img/share/facebooklikebutton.png]]
* Twitter: [IMG[https://www.smartmessages.net/img/share/tweet.png]]
* Google +1: [IMG[https://www.smartmessages.net/img/share/googleplusone.png]]
* ~LinkedIn: [IMG[https://www.smartmessages.net/img/share/linkedinshare.png]]
Where possible we have used official images for these buttons so they look the same as buttons for these services seen elsewhere, which unfortunately means they are sometimes not the same size or shape, but they will look familiar to recipients.
Here are the same buttons rendered in a web page:
[IMG[images/socialnetworkbuttons.png]]
as you can see, the dynamic versions often include additional features and thus look slightly different.
!Reporting
We request information about sharing activity from the social networks whenever we update your mailshot reports, and present it on our reporting pages. There may be some lag between shares happening and the stats being updated.
If a recipient receives a message they don't want, they often have two choices: unsubscribe from the list, or report the message as spam. All of our messages contain a working [[unsubscribe link|Unsubscribes]], and we also populate the "~List-Unsubscribe" header, making it as easy as possible for recipients to remove themselves from lists, however, some will still click the "report as spam" button. Most of the time this is not very helpful – it often won't stop them receiving messages because we don't get to find out about it (unlike unsubscribes), and it can adversely affect the delivery to those who do wish to receive them. Fortunately there is a little light at the end of the tunnel – some ~ISPs provide spam report data whenever someone reports a message as spam. Unfortunately, some don't do it at all, and some make it difficult to receive such messages. AOL is a shining example of how to do it right – not only do they provide the reports with a minimum of fuss, but they are in a format (Defined by an open standard – [[RFC 3462|http://www.faqs.org/rfcs/rfc3462.html]]) that's easy for us to process automatically. When other ~ISPs see the light, we will add them to our spam report handler.
Yahoo! requires that you use [[DKIM|DKIM and DomainKeys]] in order to receive spam reports.
!!What happens when we receive a spam report?
For the ~ISPs that we receive reports from, we process spam reports automatically, as soon as they are received. The address that the original message was sent to is unsubscribed from all lists within the account that the spam reported message was sent from, and a block is placed on that address so that no messages will ever be sent there again – a spam report has such bad consequences for deliverability that it's simply not worth risking them for the sake of a single address. The address will be suppressed from any subsequent list uploads and prevented from subscribing in future. Until the market recovers from the damage caused by the "never click an unsubscribe link" myth, we have little choice in this approach.
''Welcome to Smartmessages Help''. This is here to help you to use our service as easily as possible. Anything else you need help with? [[Ask us|ContactUs]]!
!The parts of email marketing:
*[[What you send|Templates]]
*[[Who you send it to|MailingLists]]
*[[How & when you send it|SendingMailings]]
*Tracking [[opens|Open Tracking]] and [[clicks|Link Tracking]]
*[[What happened after you sent it|Reporting]]
*[[Mailing list|MailingLists]] management – [[unsubscribes|Unsubscribes]]/[[subscribes|Subscribing]], [[bounces|Bounces]] and [[spam notifications|SpamReports]]
Smartmessages does all these things for you.
Have a browse around this ~Wiki. Click topics on the right and they will appear in this middle area.
!!Technical Info
If you're looking for technical info to integrate Smartmessages services into your site, you're in the right place.
*[[Creating custom sign-up/subscription forms|Subscribing]]
*[[Creating custom unsubscribe forms|Unsubscribes]]
*[[Complete programmable API|API]] with [[sample code|APIExamples]]
*[[Callbacks for real-time integration|Callbacks]]
*[[Using Google Analytics|GoogleAnalytics]]
*Authenticating your email with [[SPF]] and [[DKIM|DKIM and DomainKeys]]
*Adding [[custom branding|Branding]] to standard Smartmessages pages
@font-face {
font-family: 'Titillium Web';
font-style: normal;
font-weight: 400;
src: local('Titillium Web'), local('TitilliumWeb-Regular'), url('https://themes.googleusercontent.com/static/fonts/titilliumweb/v1/7XUFZ5tgS-tD6QamInJTcZ_o9VAbKgK36i-4snuAuCM.woff') format('woff');
}
@font-face {
font-family: 'Titillium Web';
font-style: normal;
font-weight: 600;
src: local('Titillium WebSemiBold'), local('TitilliumWeb-SemiBold'), url('https://themes.googleusercontent.com/static/fonts/titilliumweb/v1/anMUvcNT0H1YN4FII8wprx3QmhlKDgQgT1VN2Ed1WFo.woff') format('woff');
}
@font-face {
font-family: 'Titillium Web';
font-style: normal;
font-weight: 700;
src: local('Titillium WebBold'), local('TitilliumWeb-Bold'), url('https://themes.googleusercontent.com/static/fonts/titilliumweb/v1/anMUvcNT0H1YN4FII8wpr_5rZpfU3XI-FvUPGDRT0xY.woff') format('woff');
}
@font-face{
font-family:'DINSchrift Alternate';
src: url("font/dinengschrift-alternate-webfont.eot");
src: url("font/dinengschrift-alternate-webfont.eot?#iefix") format("embedded-opentype"),
url("font/dinengschrift-alternate-webfont.woff") format("woff"),
url("font/dinengschrift-alternate-webfont.ttf") format("truetype"),
url("font/dinengschrift-alternate-webfont.svg#dinschriftalternate") format("svg");
font-weight:normal;
font-style:normal
}
@font-face {
font-family: 'Roboto Mono';
font-style: normal;
font-weight: 500;
src: local('Roboto Mono Medium'), local('RobotoMono-Medium'), url(http://fonts.gstatic.com/s/robotomono/v4/N4duVc9C58uwPiY8_59Fz3JuJo8UJJfpGKt7pXjBv4s.woff2) format('woff2'), url(http://fonts.gstatic.com/s/robotomono/v4/N4duVc9C58uwPiY8_59Fz6TA90I55Xt7owhZwpPnMsc.woff) format('woff');
}
h1, h2, h3, h4, h5, h6, div.title {
font-family: "DINSchrift Alternate", Arial, sans-serif;
font-weight: 500;
text-shadow: 0.1em 0.1em 0.2em rgba(0, 0, 0, 0.1);
text-rendering: optimizelegibility;
margin-top: 0.4em;
}
h1, .title {
font-size: 37px;
line-height: 37px;
padding: 3px 6px;
background-color: #F9DDA0;
border-bottom: none;
}
.title {
background-color: #F8CB66;
margin: 0 0 3px;
padding: 3px 6px;
}
h2 {
font-size: 29px;
line-height: 36px;
padding: 3px 6px;
background-color: #F9DDA0;
border-bottom: none;
}
h3 {
font-size: 22px;
line-height: 32px;
padding: 0;
border-bottom: 2px solid #F8CB66;
}
h4 {
font-size: 16px;
line-height: 18px;
}
h5 {
font-size: 13px;
line-height: 18px;
}
h6 {
font-size: 11px;
line-height: 16px;
}
body, p, td, th, span, div, a, input, textarea {
font-family: "Titillium Web","Trebuchet MS","Lucida Grande","Lucida Sans",Tahoma,sans-serif;
font-size: 15px;
line-height:19px;
}
strong {
font-weight: 700;
}
p {
margin: 0 0 9px;
}
.header {
background-color: #333;
}
.viewer code, .viewer pre {
font-size: 1.0em;
font-family: "Roboto Mono", Inconsolata, Monaco, monospace;
font-weight: 500;
color: #11100C;
}
.viewer th {
color: #333;
background-color: #F9DDA0;
}
img {
margin: 4px 0;
box-shadow: 0.1em 0.1em 0.4em rgba(0,0,0,.15);
}
There are several ways that people can subscribe to your lists. In order of increasing complexity and flexibility:
* A simple signup link
* Our standard signup form
* A custom form using our processor
* A custom form built with a WordPress form builder
* A custom form using our [[API]]
On the contacts page you'll see a list of your mailing lists, and each one has a "Link" link which will take you to a subscribe page for that list, for example https://www.smartmessages.net/subscribe/1886. If you want to add a simple subscribe link to your own pages, you should use whichever of those links is appropriate. The default form captures just the email address and a single-field name. If you want more than that, you can build your own form.
!!Ready-to-roll signup forms
If you click on 'manage' on the contacts page to look at an individual mailing list, you'll see a tab in the actions section called 'Signup form'. In there you'll find a text box containing a ready-to-use HTML form for that list. Just select it, copy it and paste it into your own site's HTML.
!!Custom signup forms
Many of our customers want to use their own web forms to submit information to our subscription processor, and that's also easy to do – just point your form's action at https://www.smartmessages.net/subscribe.php. The standard ready-to-roll form we provide has lots more options available in its processor via the following parameters (bold fields are required):
*''//command//'' – the value 'subscribe'
*''//emailaddress//'' – the email address of the new subscriber
*''//mlid//'' – the ID of the mailing list they are subscribing to (this is the value that's visible in the "link" links on the contacts page)
*//allow_tracking// – a checkbox for optional open and click tracking consent with a {{{value}}} of {{{1}}}; must default to unchecked for GDPR/ePD compliance, and defaults to off if omitted
*//title// – 'Mr', 'Miss', 'Dr.', 'Herr' etc.
*//dear// – a straightforward single-field name that actually corresponds with our 'dear' field
*//firstname// – the subscriber's first name
*//lastname// – the subscriber's last name
*//companyname// – the subscriber's company name
*//postcode// – the subscriber's postcode
*//language// – the subscriber's preferred language (2-character ISO 639-1 code, e.g. {{{en}}}, {{{fr}}}, {{{de}}}, defaults to {{{en}}})
*//country// – the subscriber's country (2-character ISO 3166 code e.g. {{{GB}}}, {{{FR}}}, {{{DE}}}, defaults to {{{GB}}})
*//redirect// – a URL to go to after processing the subscription request instead of displaying our own default page (don't forget to ~URL-encode it)
*//json// – any value – its presence will indicate that you want a response in a JSON format (e.g. you're subscribing from ~Javascript)
By building your own form and providing a redirect URL, you can use our subscribe processor completely transparently and invisibly to your users. If you specify a redirect URL, you will receive an HTTP GET request to that URL containing your submitted parameters (so you can process it further – for example add it to your own contact database) along with additional information about the success (or not) of the subscription request in a {{{statuscode}}} parameter. This has the following meanings:
*1 – Success
*2 – Already subscribed
*3 – Internal error
*4 – Missing required parameters
*5 – Invalid email address
*6 – Invalid mailing list ID
The JSON output also includes a {{{success}}} value that is true for codes 1 and 2, false for others, along with a {{{message}}} value containing a plain-text explanation of the response.
Here's a minimal example form that you can adapt:
{{{
<form action="https://www.smartmessages.net/subscribe.php" method="post">
<p>
<input type="hidden" name="command" value="subscribe">
<input type="hidden" name="mlid" value="<insert your mailing list ID here>">
Name: <input type="text" name="dear">
Email address: <input type="text" name="emailaddress">
I consent to tracking opens and clicks (optional): <input type="checkbox" name="allow_tracking" value="1"><br>
<input type="submit" name="Subscribe">
</p>
</form>
}}}
Of course you can add more input fields from the list above.
If you want subscribers to be able to choose from multiple lists, create an HTML select input with multiple options for the different mailing lists' ~IDs you want.
!!Landing page
Every Smartmessages account gets to use our simple landing page which includes data capture of all standard fields and the option to subscribe to all mailing lists that are marked as visible. You'll find the link to your landing page on the "Contacts" page after you log into Smartmessages.
!!API
If you are undertaking more complex integrations (for example capturing custom fields or a full postal address) then you will be better served by the {{{subscribe}}} and {{{setUserInfo}}} functions in our [[API]].
A suppression list is an "anti-mailing list" – a list of people that you do NOT want to mail.
We maintain several different kinds of suppression list:
*Unsubscribes
*Manual suppressions (for example people that phoned you up to ask to be unsubscribed)
*Spam reporters
*Persistent bouncers
[[Spam reporters|SpamReports]] are always applied account-wide, to all your mailing lists, so if someone reports one of your messages as spam, they will be removed from all your lists and prevented from being uploaded to all mailing lists in future. The small increase in delivery count you might get from persisting with such recipients is far outweighed by the negative impact it can have on your deliverability to everybody else. You can download a list of the people who have reported your messages as spam on the contact page.
Persistently [[bouncing|Bounces]] addresses are the only thing we share across all accounts, so you can benefit from some level of list cleaning simply by uploading your list before you have sent anything, just because one of our other customers may already have ascertained that some addresses bounce persistently. This bounce list is not available for download.
We do not currently have a mechanism for suppressing entire domains, but it's something we are considering.
When you do a list upload, all addresses that match any of these suppressions are removed before they are added to your list.
!!Removing suppressions
Sometimes you might want to undo or remove a suppression, for example if you unsubscribed yourself while testing. Each mailing list page has an 'add a single subscriber' option, and if you enter an email address here, any suppressions they have will be removed, and they will be subscribed to your list. We consider that if you have sufficient administrative privileges, then adding a single address is something we will allow. Similarly, anyone completing a double-opt-in subscription will have suppressions removed, not least because this requires explicit opt-in (which we consider a reasonable request to override any previous opt-out), and can't be done to a bouncing address. In short, suppressions are ONLY applied while uploading lists.
!!Global Unsubscribe
You'll see something called "Global unsubscribe" mentioned on our contacts page. This parameter controls what happens when someone unsubscribes, and it can be ON (the default) or OFF. This is a parameter we maintain control over, and you need to ask us if you'd like it changed.
!!!Global unsubscribe ON
If global unsubscribe is ''ON'', when someone unsubscribes from ''ONE'' of your lists, they will be removed from ''ALL'' of your lists. They are added to a suppression list that will prevent them from being uploaded into ''ANY'' list. This is the default mode of operation, and is equivalent to what most other email providers do too.
!!!Global unsubscribe OFF
If global unsubscribe is ''OFF'', when someone unsubscribes from ''ONE'' of your lists, they will be removed from ''ONLY'' that list. They will be added to a suppression list linked to only that list. Subscriptions of that address to other lists will be unaffected, and you will be able to upload them into other lists.
We maintain this policy because of the following scenario:
* Customer uploads their address list into Smartmessages.
* They send a few mailshots to it.
* Records of bounces, unsubscribes, spam reports and other usage data accumulates in Smartmessages.
* Customer uploads their original (or their own new version) address list into a new list on Smartmessages.
At this point with global unsubscribe OFF, sending to the new list would be illegal because it would contain people that had unsubscribed. For this reason, we will only turn off global unsubscribe for customers who can demonstrate that they are handling their data with sufficient care that they don't run into this problem.
Some of our customers want to integrate their mailings with surveys using services like [[SurveyMonkey|http://www.surveymonkey.com/]] and packages like [[LimeSurvey|http://www.limesurvey.org/]]. Here are some integration notes.
!!~SurveyMonkey
~SurveyMonkey doesn't preload lists of potential respondents, instead it relies on collecting details of those that do respond. This means that they can't prevent unauthorised people accessing the survey, and also that they can't offer any data pre-population or personalisation. On the upside, it also means there is very little setup required. To connect Smartmessages messages to a survey, you need to use their [[web collector|http://help.surveymonkey.com/articles/en_US/kb/How-do-I-send-my-survey-to-respondents-or-get-responses-to-my-survey]], and you'll generate ~URLs to feed into it using our template or mailshot editor. You need to start with a link to the anonymous survey entry point and add a unique identifier for each recipient – their email address will do nicely, though we need to ~URL-escape it as it is embedded in a URL. So a base URL for your survey (obtained through your ~SurveyMonkey account interface) that you link to from your message template might be:
{{{
http://www.surveymonkey.com/s.aspx?sm=v8MbvURxoHkWfvud7Or3Cg_3d_3d
}}}
You then need to add a 'c' paramater to it like this:
{{{
http://www.surveymonkey.com/s.aspx?sm=v8MbvURxoHkWfvud7Or3Cg_3d_3d&c=[[$subscriber.email|escape:'url']]
}}}
After your survey is complete you can download the results from ~SurveyMonkey.
For those that like to know such things, here is some technical background on Smartmessages.
* Built in PHP 7.4
* Message generation using [[PHPMailer|https://github.com/PHPMailer/PHPMailer]] (of which we are the maintainers)
* Tested with ~SimpleTest
* Templates (for both site and messages) with Smarty
* Percona Server ~MySQL 5.7 database cluster
* Memcached distributed cache
* Run on Ubuntu Linux
* [[CKEditor|http://ckeditor.com]] WYSIWYG editor and [[CKFinder|http://cksource.com/ckfinder]] file selector
* Last and definitely not least, ~GreenArrow qmail-based mail servers, capable of > 2million messages/hour per server!
We have support for converting from some other email systems' template formats. [[Our templating system|TemplateUploads]] is so powerful and flexible that we generally have no problem in providing //everything// that our competitors do, plus lots more, all with simplicity and consistency. This helps ease migration to Smartmessages, and in some cases if you prefer the way that other editors work, you can still use them while using Smartmessages for your sends. We currently have support for these formats:
* Old Smartmessages, using tags like {{{[[unsubscribe]]}}}
* Mailchimp, using tags like {{{*|UNSUB|*}}}
* Campaign Monitor, using tags like {{{[unsubscribe]}}}
* Pure360, using tags like {{{{~tagname~} }}}
* Eshot, using tags like {{{*unsubscribe*}}}
* Mizmoz, using tags like {{{{{unsubscribe}} }}}
* ~MailPoet, using tags like {{{[link:subscription_unsubscribe_url]}}}
We are very interested in adding support for other formats – so if there's one you particularly need, please [[ask us|ContactUs]], and ideally, provide a link to appropriate technical documentation. If you find any issues with our conversions, please let us know – for example it's often unclear in documentation whether a tag renders to a complete HTML link tag or just a URL. These conversions are supported only via the [[Templates page|TemplateUploads]] – the workflow is essentially paste in your template, select the 'Convert template format' checkbox and click Save. Details on individual conversions can be found below.
!!!How complete are conversions?
While we may support a template //format// comprehensively, we don't necessarily have identical //features// – for example Mailchimp has tags relating to their rewards system, and obviously that's something that is specific to them. Similarly, Pure360 doesn't really have a templating system, but drives things from account-wide settings. Wherever possible we provide exact conversions, failing that nearest equivalents, or in some cases we have to drop the tags – see the notes below for detailed information. Correspondingly, we also have features that other systems do not, and you can't take advantage of them using another system's template format. Conversions are applied in subject line templates, HTML and plain-text templates, and are also available through our [[API]]. You should ''always check and test your templates after conversion'' to ensure everything is as you expect.
!!Old Smartmessages
Previously we had a two-tier template system with a complicated mechanism to allow re-use of template 'shells' containing editable chunks. This was great for template re-use, but was really not very dynamic. It was also based entirely on functional tags rather than simple variables, lacked output controls, conditions and many other things. In 2014 we changed to a new template system that uses a simpler overall structure, but is far more powerful and dynamic. Because this was our own template system we are able to provide complete compatibility in both template format and features.
!!Mailchimp
Mailchimp is extremely popular, especially for those that don't mind placing ads in their messages and have explicit permission to export subscriber data to the US. They have an excellent drag & drop editor, based on the same editor that we use. You can find their tag documentation [[here|http://kb.mailchimp.com/merge-tags/all-the-merge-tags-cheatsheet]]. The template syntax is somewhat haphazard and inconsistent; for example {{{*|ABOUT_LIST|*}}} and {{{*|LIST:DESCRIPTION|*}}} are both things to do with a list but use different formats; {{{*|LIST:NAME|*}}} shows the name property of a list, but {{{*|URL:MMERGE1|*}}} applies URL escaping to the ~MMERGE1 field; Tag parameters are sometimes specified as {{{*|TAG:parametervalue|*}}} but at other times as {{{*|TAG [$parameter=value]|*}}}. Nevertheless, we support all of these tags through predefined variables, functional tags, modifiers, and built-in features of our templating system, resulting in much more consistent syntax.
Some tags will require some manual cleaning up after conversion, in particular anything involving conditions (e.g. {{{IF}}}, {{{IFNOT}}} and {{{GROUP}}} tags). Our RSS conversion (for the {{{FEEDBLOCK}}} tag) is very thorough, but because it's such a complex structure, you will need to pay close attention to the converted output. As always, ''test'', ''test'', ''test'' your templates before sending!
!!!Custom tag names
Mailchimp templates can contain tags with custom names that are unique to your Mailchimp account. The problem with them is that the list of valid custom tags is not contained in the template, so we can't tell if {{{*|BLAH|*}}} is a custom field, or whether it should be flagged as an error. To allow the use of these custom tags, all unidentified tags are left unconverted, and you will need to convert them manually. All custom tags also have a default name like {{{*|MMERGEn|*}}}, where {{{n}}} is replaced with the custom field's number, and we convert these names correctly to our own numbered custom tags, though of course you'll also need to import your data into these fields to have them show anything.
!!!Images
Images referenced with relative ~URLs starting with {{{/images/}}} will work correctly if you simply drag and drop your images into the Files tab in Smartmessages.
!!!Supported tags
|!Tag |!Notes |
|{{{*|ABOUT_LIST|*}}}||
|{{{*|ABUSE_EMAIL|*}}}||
|{{{*|ARCHIVE|*}}}||
|{{{*|ARCHIVE_LINK_SHORT|*}}}|Replacement is not shortened|
|{{{*|BLIPTV|*}}}|See [[Video]]|
|{{{*|BRAND:LOGO|*}}}|This results in a URL, not an {{{img}}} tag. See also the {{{$account.logo}}} image tag.|
|{{{*|CAMPAIGN_UID|*}}}||
|{{{*|CURRENT_YEAR|*}}}||
|{{{*|DATE|*}}}|With and without format string|
|{{{*|ELSE|*}}}||
|{{{*|ELSEIF:LANGUAGE|*}}}||
|{{{*|ELSEIF:MC_LANGUAGE|*}}}||
|{{{*|EMAIL_UID|*}}}||
|{{{*|EMAIL|*}}}||
|{{{*|END:FEEDBLOCK|*}}}||
|{{{*|END:FEEDITEMS|*}}}||
|{{{*|END:IF|*}}}||
|{{{*|FACEBOOK:LIKE|*}}}|With and without custom URL|
|{{{*|FACEBOOK:PROFILEURL|*}}}||
|{{{*|FEED|*}}}||
|{{{*|FEED:DATE|*}}}||
|{{{*|FEED:DESCRIPTION|*}}}||
|{{{*|FEED:TITLE|*}}}||
|{{{*|FEED:URL|*}}}||
|{{{*|FEEDBLOCK|*}}}||
|{{{*|FEEDITEM:AUTHOR|*}}}||
|{{{*|FEEDITEM:CATEGORIES|*}}}||
|{{{*|FEEDITEM:COMMENTS_URL|*}}}||
|{{{*|FEEDITEM:CONTENT_FULL_TEXT|*}}}||
|{{{*|FEEDITEM:CONTENT_FULL|*}}}||
|{{{*|FEEDITEM:CONTENT_TEXT|*}}}||
|{{{*|FEEDITEM:CONTENT|*}}}||
|{{{*|FEEDITEM:DATE|*}}}||
|{{{*|FEEDITEM:ENCLOSURE_URL|*}}}||
|{{{*|FEEDITEM:ENCLOSURE|*}}}||
|{{{*|FEEDITEM:IMAGE|*}}}||
|{{{*|FEEDITEM:LIKE|*}}}||
|{{{*|FEEDITEM:PLUSONE|*}}}||
|{{{*|FEEDITEM:SOURCE_TITLE|*}}}||
|{{{*|FEEDITEM:SOURCE|*}}}||
|{{{*|FEEDITEM:TITLE|*}}}||
|{{{*|FEEDITEM:TWITTER|*}}}||
|{{{*|FEEDITEMS|*}}}||
|{{{*|FNAME|*}}}||
|{{{*|FORWARD|*}}}||
|{{{*|GOOGLE:PLUSONE|*}}}|With and without custom URL|
|{{{*|GROUP:A|*}}}||
|{{{*|GROUP:B|*}}}||
|{{{*|HTML:LIST_ADDRESS_HTML|*}}}||
|{{{*|HTML:MMERGE|*}}}||
|{{{*|HTML:REWARDS|*}}}||
|{{{*|HTML:USER_ADDRESS_HTML|*}}}||
|{{{*|IF:ARCHIVE_PAGE|*}}}||
|{{{*|IF:LANGUAGE|*}}}||
|{{{*|IF:MC_LANGUAGE|*}}}||
|{{{*|IF:REWARDS|*}}}||
|{{{*|IF|*}}}|Converted, but will need manual cleanup|
|{{{*|IFNOT:ARCHIVE_PAGE|*}}}||
|{{{*|IFNOT|*}}}|Converted, but will need manual cleanup|
|{{{*|LIST_HOST|*}}}||
|{{{*|LIST:ADDRESS_VCARD_HREF|*}}}||
|{{{*|LIST:ADDRESS_VCARD|*}}}||
|{{{*|LIST:ADDRESS|*}}}||
|{{{*|LIST:COMPANY|*}}}||
|{{{*|LIST:DESCRIPTION|*}}}||
|{{{*|LIST:EMAIL|*}}}||
|{{{*|LIST:NAME|*}}}||
|{{{*|LIST:PHONE|*}}}||
|{{{*|LIST:RECENT(d+)|*}}}||
|{{{*|LIST:RECENT|*}}}||
|{{{*|LIST:SUBSCRIBE|*}}}||
|{{{*|LIST:SUBSCRIBERS|*}}}||
|{{{*|LIST:UID|*}}}||
|{{{*|LIST:URL|*}}}||
|{{{*|LNAME|*}}}||
|{{{*|LOWER:MMERGE|*}}}||
|{{{*|MC_LANGUAGE_LABEL|*}}}||
|{{{*|MC_LANGUAGE|*}}}||
|{{{*|MC_PREVIEW_TEXT|*}}}|Converted to a {{{[[preheader]]}}} tag. [[More info|PreHeaders]].|
|{{{*|MC:DATE|*}}}||
|{{{*|MC:SHARE|*}}}||
|{{{*|MC:SUBJECT|*}}}||
|{{{*|MC:TOC_TEXT|*}}}||
|{{{*|MC:TOC|*}}}||
|{{{*|MC:TOPSHARE|*}}}||
|{{{*|MC:TRANSLATE|*}}}||
|{{{*|MMERGE(d+)|*}}}||
|{{{*|OPTIN_DATE|*}}}||
|{{{*|OPTIN_DATETIME|*}}}||
|{{{*|REWARDS_TEXT|*}}}||
|{{{*|REWARDS|*}}}||
|{{{*|SHARE|*}}}||
|{{{*|SHARELINK:TWITTER|*}}}||
|{{{*|SHARELINK:FACEBOOK|*}}}|Uses 'like'|
|{{{*|SHARELINK:LINKEDIN|*}}}||
|{{{*|TITLE:MMERGE|*}}}||
|{{{*|TRANSLATE|*}}}||
|{{{*|TWITTER:PROFILEURL|*}}}||
|{{{*|TWITTER:TWEET|*}}}|With and without custom text|
|{{{*|UNIQID|*}}}||
|{{{*|UNSUB|*}}}||
|{{{*|UPDATE_PROFILE|*}}}||
|{{{*|UPPER:MMERGE|*}}}||
|{{{*|URL:ARCHIVE_LINK_SHORT|*}}}|Replacement is not shortened|
|{{{*|URL:MMERGE|*}}}||
|{{{*|USER:ADDRESS|*}}}||
|{{{*|USER:COMPANY|*}}}||
|{{{*|USER:PHONE|*}}}||
|{{{*|USER:UID|*}}}||
|{{{*|USER:URL|*}}}||
|{{{*|VIMEO|*}}}|See [[Video]]|
|{{{*|YOUTUBE|*}}}|See [[Video]]|
!!!Unsupported tags
These tags are either irrelevant or unnecessary in our system, or pertain to Mailchimp features we don't have.
|!Tag |!Notes |
|{{{*|AUTOMATION|*}}}||
|{{{*|COUPON|*}}}||
|{{{*|END:GROUP|*}}}||
|{{{*|END:INTERESTED|*}}}||
|{{{*|FACEBOOK:FULLPROFILE|*}}}||
|{{{*|FACEBOOK:POSTS|*}}}||
|{{{*|FACEBOOK:PROFILE|*}}}|With or without ID|
|{{{*|FEED:POSTS|*}}}|Use {{{simplerss}}} instead, [[read more|RSS]]|
|{{{*|FEEDITEM:INSTAPAPER|*}}}||
|{{{*|FEEDITEM:TUMBLR|*}}}||
|{{{*|INTERESTED|*}}}||
|{{{*|LIST:SUBSCRIBER_BADGE|*}}}||
|{{{*|LOCAL:DEALS|*}}}||
|{{{*|LOCAL:EVENTS|*}}}||
|{{{*|POLL|*}}} – {{{*|END:POLL|*}}}|Entire poll block is removed|
|{{{*|QRCOUPON|*}}}||
|{{{*|RSS|*}}}|Use {{{rss}}} or {{{simplerss}}} tags instead, [[read more|RSS]]|
|{{{*|SURVEY|*}}}||
|{{{*|TWITTER:FULLPROFILE|*}}}||
|{{{*|TWITTER:PROFILE|*}}}|With or without ID|
|{{{*|TWITTER:TWEETS|*}}}||
!!Campaign Monitor
Some Campaign Monitor template tags appear in two formats: {{{[tagname]}}} and {{{<tagname>}}}; this generally means they contain plain text or HTML content respectively, but that's not always consistent – sometimes they are interchangeable, sometimes not, so you may need to tweak them appropriately. Some tags are context sensitive – for example the {{{<fblike>}}} tag will use an RSS item's URL if it's inside a {{{datarepeater}}} (RSS) block. Smartmessages doesn't do that, so such tags will require manual cleanup.
!!!Custom tag names
Much like Mailchimp, Campaign Monitor has a mechanism for defining custom tag names, and this information is not available in templates, so unrecognised tags are left unconverted and will require manual conversion, along with other tags that can use field names, such as {{{[if:]}}}.
!!!Supported tags
|!Tag |!Notes |
|{{{[firstname]}}}|Including fallback option|
|{{{[lastname]}}}|Including fallback option|
|{{{[fullname]}}}|Including fallback option|
|{{{[email]}}}||
|{{{<currentday>}}}||
|{{{<currentdayname>}}}||
|{{{<currentmonth>}}}||
|{{{<currentmonthname>}}}||
|{{{<currentyear>}}}||
|{{{<unsubscribe>}}}|Including optional content|
|{{{[unsubscribe]}}}||
|{{{<webversion>}}}|Including optional content|
|{{{[webversion]}}}||
|{{{<forwardtoafriend>}}}|Including optional content and language option|
|{{{<preferences>}}}|Including optional content and language option|
|{{{[preferences]}}}|Including language option|
|{{{[if:]}}}|Will require manual cleanup|
|{{{[elseif:]}}}|Will require manual cleanup|
|{{{[else]}}}||
|{{{<fblike>}}}|Including optional content and target URL|
|{{{<tweet>}}}|{{{via}}} and {{{recommend}}} options not supported|
|{{{[tweet]}}}|{{{via}}} and {{{recommend}}} options not supported|
|{{{cm_dontconvertlink}}}||
|{{{cm_dontimportimage}}}||
|{{{<singleline>}}}|Enclosed content converted as-is|
|{{{<multiline>}}}|Enclosed content converted as-is|
|{{{<repeater>}}}|Enclosed content converted as-is|
|{{{<layout>}}}|Enclosed content converted as-is|
|{{{<tableofcontents>}}}|Partial conversion using {{{[[[toc]]]}}} tag|
|{{{<datarepeater type="rss"...}}}|Will require manual cleanup|
|{{{<rsstitle>}}}||
|{{{<rssauthor>}}}||
|{{{<rssitemday>}}}||
|{{{<rssitemdayname>}}}||
|{{{<rssitemmonth>}}}||
|{{{<rssitemmonthname>}}}||
|{{{<rssitemyear>}}}||
|{{{<rssimage>}}}|With and without width|
|{{{<rssitemlink>}}}|With and without content|
|{{{<rsscommentlink>}}}|With and without content|
|{{{<rssbody>}}}|Paragraph count not supported|
!!!Unsupported tags
|!Tag |!Notes |
|{{{[ifmemberof:]}}}||
|{{{<repeatertitle>}}}|Will need manual conversion to HTML id attributes|
!!Pure360
Pure 360 doesn't officially have a templating system! In reality they do, though it's only very basic. Many template features in Pure 360 are implemented as account-level settings; for example if you want a default value to use in the absence of a first name field, you must set it in your preferences; this doesn't happen at a template level. For RSS content generation, you need to pre-define your feeds, then build ~RSS-specific 'regions' in your account that use them, and then pull those regions into your templates – you can't drive it all directly from a template as in Smartmessages. Some critical ~URLs are generated from fragments, in particular the unsubscribe and web version ~URLs, so there is no single tag for them; Where possible we spot these URL patterns and replace them with our equivalent tags.
!!!Custom tag names
Like Mailchimp and Campaign Monitor, Pure360 allows you to define custom field names. In common with them, that means tags can't be checked for validity outside of Pure360, so we leave unrecognised tags unconverted and you will need to assign them manually after conversion.
As always you should ''inspect and test your templates thoroughly after conversion''.
!!!Supported tags
|!Tag |!Notes |
|{{{{~email~} }}}||
|{{{{~subject~} }}}||
|{{{{~listname~} }}}||
|{{{{~mailId~} }}}|Generally not needed|
|{{{{~FIRSTNAME~} }}}||
|{{{{~LASTNAME~} }}}||
|{{{{~region~xyz~} }}}|Converted to an {{{[[if]]}}} block placeholder, will need cleanup|
|{{{{~mailVariationId~} }}}|Converted to an {{{[[if]]}}} block placeholder, will need cleanup|
|{{{{~RSS-channel-link~} }}}||
|{{{{~RSS-channel-title~} }}}||
|{{{{~RSS-item-link~} }}}||
|{{{{~RSS-item-title~} }}}||
|{{{{~RSS-item-date~} }}}|Pure does not provide date formatting options|
|{{{{~RSS-item-description~} }}}||
|{{{{~RSS-channel-link~} }}}||
!!!Unsupported tags
|!Tag |!Notes |
|{{{{~customDomain~} }}}|Mapped to {{{www.smartmessages.net}}}|
|{{{{~deviceBrowser~} }}}||
|{{{{~deviceOS~} }}}||
|{{{{~deviceType~} }}}||
!!Mizmoz
Mizmoz only has a very basic selection of template fields, and the format is a bit inconsistent.
!!!Custom tag names
Mizmoz allows you to define custom field names in a pattern like {{{{{user.meta.*}} }}}. This means tags can't be checked for validity outside of Mizmoz, so we convert them literally and you will need to reassign them manually after conversion – for example {{{{{user.meta.shoesize}} }}} will be converted to {{{[[$subscriber.shoesize]]}}}, which won't work, but you will be able to map it manually, perhaps to a numbered custom field.
As always you should ''inspect and test your templates thoroughly after conversion''.
!!!Supported tags
|!Tag |!Notes |
|{{{{{user.title}} }}}||
|{{{{{user.firstname}} }}}||
|{{{{{user.lastname}} }}}||
|{{{{{user.email}} }}}||
|{{{{{user.list}}} }}||
|{{{{{user.listId}} }}}||
|{{{{{user.hash}} }}}||
|{{{{{subject}} }}}||
|{{{{{fromName}} }}}||
|{{{{{fromEmail}} }}}||
|{{{{{unsubscribe}} }}}|Plain URL|
|{{{{{preferences}} }}}|Plain URL|
|{{{{{viewOnline}} }}}|Plain URL|
|{{{{{forward}} }}}|Plain URL|
|{{{{{shareCampaign}} }}}|See {{{[[share]]}}} tag|
|{{{{{shareFacebook}} }}}||
|{{{{{shareTwitter}} }}}||
|{{{{{IF}} }}}|Some conditions may need additional checking, {{{user.meta.*}}} properties in conditions are not converted|
|{{{{{IFNOT}} }}}||
|{{{{{ELSE}} }}}||
|{{{{{ENDIF}} }}}||
|{{{{{user.meta.*}} }}}|See notes above|
!!Eshot
Eshot don't provide any public documentation on their template format, so our conversion is only simple and is derived from templates we have seen. Got any better info? Let us know!
!!!Supported tags
|!Tag |!Notes |
|{{{*MyEshotUrl*}}}||
|{{{*unsubscribe*}}}||
|{{{*ForwardtoFriendURL*}}}||
|{{{*companyinfo*}}}||
!!~MailPoet
~MailPoet is a WordPress plugin, so its sending context is thus a little different, and we can't support tags like "post_title". This conversion is based on their documentation, which may be incomplete. They support custom tags, but their definitions are not embedded in the templates, so you'll need to handle those yourself.
!!!Supported tags
|!Tag |!Notes |
|{{{[subscriber:firstname]}}}|Also supports {{{default}}} modifier|
|{{{[subscriber:lastname]}}}|Also supports {{{default}}} modifier|
|{{{[subscriber:displayname]}}}|Also supports {{{default}}} modifier|
|{{{[subscriber:email]}}}||
|{{{[newsletter:subject]}}}||
|{{{[newsletter:total]}}}|Renders to nothing|
|{{{[newsletter:post_title]}}}|Renders to nothing|
|{{{[newsletter:number]}}}|Renders to nothing| |
|{{{[mailpoet_archive]}}}|Maps to {{{[[history]]}}}|
|{{{[date:d]}}}||
|{{{[date:dordinal]}}}|Renders to nothing|
|{{{[date:dtext]}}}||
|{{{[date:m]}}}||
|{{{[date:mtext]}}}||
|{{{[date:y]}}}||
|{{{[date:custom | format:<format string>]}}}|Uses incompatible format string, so maps to {{{[[$system.now|date_format:"%Y-%m-%d"]]}}}|
|{{{[link:subscription_unsubscribe_url]}}}||
|{{{[link:subscription_manage_url]}}}||
|{{{[link:newsletter_view_in_browser_url]}}}||
|{{{[site:title]}}}|Maps to {{{[[$account.name]]}}}|
|{{{[site:homepage_url]}}}||
This describes all the tags, variables and functions you can use when building your templates. Before getting into this, you should be familiar with our [[basic template syntax|TemplateSyntax]].
!HTML and plain text
There are two parts to a template:
* ''HTML'' contains markup source that the mail client will render in a similar way to how a browser renders a web page.
* ''Plain text'' is used to generate a markup-free version that's used by simpler email clients, including some mobile clients (e.g. Blackberry, Pine, Mutt).
Email messages are constructed in a way that uses both HTML and plain parts, and tells receiving programs to prefer the HTML version, but fall back to the plain text one if it's not able to display it. It's important to include both versions of your content so that recipients can choose how to read it, and many spam filters frown upon ~HTML-only messages.
!Subjects are dynamic too
Subject lines added via the template page or while creating a mailshot are also fully dynamic – you can use all the same tags, variables and functions to personalise your subject lines, though be aware that HTML will not work in subject lines, you can't have line breaks, and you have a limited line length, though the limit is probably higher than you would want a subject line to be anyway. Somewhat obviously, you can't use the {{{$message.subject}}} property in a subject line or the universe will implode.
!Careful what you wish for!
Our templates are extremely powerful, tags are free-form and you can put them anywhere you like, however that also means ''you are free to build things that make no sense and will not work'', for example you can say: {{{<a href="[[$subscriber.firstname]]">click me</a>}}} which is unlikely to be useful. It's particularly the case when fields are used in ~URLs; Make sure that your ~URLs do not contain spaces, accented characters or anything else that's invalid – ~URL-encoding is always the safe option, and you can apply that to any value using the {{{escape}}} modifier (please see the notes on using quotes with modifier parameters below), for example:
{{{
<a href="http://example.com/data.php?name=[[$subscriber.informal_greeting|default:'Subscriber'|escape:'url']]">Click me</a>
}}}
!!Test, test, test!
To make sure what you produce is valid and workable as well as looking great, we strongly recommend that you make use of the preview, validation, link and image checking services Smartmessages provides, and send instant, 1-click test mailings to your test list.
!Variables
Smartmessages organises the various bits of data available to your templates into arrays of related properties. These are:
* {{{$system}}}: The Smartmessages system itself
* {{{$account}}}: Your Smartmessages account
* {{{$subscriber}}} The person a message is being sent to
* {{{$subscription}}}: The subscription of the recipient to the mailing list this mailing is being sent to
* {{{$mailshot}}}: This particular mailshot
* {{{$campaign}}}: The folder that this mailshot is placed in
* {{{$mailinglist}}}: The mailing list this mailshot is being sent to
* {{{$message}}}: The individual message being sent
These are covered in detail below. To refer to any of these elements in your templates you need to create a tag (with double square brackets) containing the variable name followed by a dot, followed by the element name you want to use, for example {{{[[$account.name]]}}}. All content is automatically escaped so that it doesn't corrupt the surrounding HTML, so if your account name is "{{{I <3 you}}}" it will render to "{{{I <3 you}}}" unless you specify the {{{nofilter}}} keyword.
Any element can be made to display a fallback/default value if it is empty by using the {{{default}}} modifier, see the modifiers section for how to use that.
!!{{{$system}}}
These elements provide useful information about the Smartmessages system itself, allowing you to construct ~URLs dynamically so that things don't break should things move around.
!!!{{{rooturl}}}
The base URL of the Smartmessages system. This is usually {{{https://www.smartmessages.net/}}}. Notice that it uses TLS.
!!!{{{rooturlnossl}}}
The same as {{{rooturl}}}, but using a non-secure http URL, so it's usually {{{http://www.smartmessages.net/}}}. There is no longer any reason to use this as Smartmessages now serves everything over secure TLS connections.
!!!{{{language}}}
A locale code of the language of this message. This is for future expansion, for now it will always be {{{en_gb}}}, indicating British English.
!!!{{{charset}}}
The character set this message uses. This used to be variable, but now will always be {{{utf-8}}}, indicating the ~UTF-8 encoding of the unicode character set.
!!!{{{library_rooturl}}}
This is the base URL of the image library Smartmessages provides. You probably don't need to use this as images using relative {{{/library}}} ~URLs are automatically remapped using it.
!!!{{{ispreview}}}
This boolean value is true when this message is viewed as a web page or preview as opposed to as an email message. See also {{{[[$message.ispersonal]]}}}.
!!!{{{now}}}
A unix timestamp of the current date and time. Convert it to a readable address using the {{{date_format}}} modifier.
!!{{{$account}}}
This holds information relating to your account as a whole, and is common to all messages in all mailshots you send. We make use of these elements in our standard templates to brand them for you.
!!!{{{name}}}
The name of your account!
!!!{{{path}}}
The name of the folder that contains your uploaded images.
!!!{{{address}}}
Your full address, as entered on the settings page. This includes line breaks, which of course are not shown in HTML output, but you can convert them to other sequences for better output using modifiers:
{{{
[[$account.address|nl2br nofilter]]
[[$account.address|stripbreaks:", "]]
}}}
The first example converts the breaks to HTML {{{<br>}}} tags; you must add the nofilter keyword to prevent the generated tags from being escaped. The second example uses the {{{stripbreaks}}} modifier, resulting in the address appearing in one line with a comma and space between each line in the original address.
!!!{{{posttown}}}
The city/town of your address; this is included in the {{{address}}} property, so you don't need to include both.
!!!{{{postcode}}}
The postcode from your address; this is included in the {{{address}}} property, so you don't need to include both.
!!!{{{companynumber}}}
It's a legal requirement to display your company number in all marketing communications in the UK, so we make it easy to get at using this tag.
!!!{{{url}}}
Your home page URL, as entered on the settings page.
!!!{{{email}}}
Your contact email address, as entered on the settings page.
!!!{{{country}}}
The name of your country, generated using standard [[ISO3166|http://www.iso.org/iso/country_codes.htm]] names in English.
!!!{{{countrycode}}}
Your [[ISO3166-1 alpha-2|http://en.wikipedia.org/wiki/ISO_3166-1_alpha-2]] country code, for example {{{GB}}} for the United Kingdom.
!!!{{{phone}}}
your default phone number, as entered on the settings page.
!!!{{{useopengraphtags}}}
A boolean value indicating whether your account is set to use [[Facebook's open graph tags|https://developers.facebook.com/docs/web/share]]. This is used when generating web versions to make your pages look better when they are shared on social networks, and is on by default.
!!!{{{trackingenabled}}}
A boolean value indicating whether subscriber message openings and clickthroughs are tracked and reported, and is on by default. This is controlled from the analytics tab in settings.
!!!{{{privacypolicy_url}}}
The URL of your privacy policy. You can set a custom policy in your account settings, but otherwise we provide one for you, and this URL will point at it.
!!!{{{subscriptionpolicy}}}
Except in some special cases, this will be the string "{{{double opt-in}}}".
!!!{{{landingpage_url}}}
The URL of your landing page, as linked from your contacts page. This is a central location where your subscribers can see and edit their own data (allowing you to fulfil the legally-required data access requests), and also manage their subscription to all your public mailing lists at once. This is a generic URL not specific to any particular subscriber – see {{{$subscriber.landingpage_url}}}.
!!!{{{imagebase_url}}}
The base URL of your uploaded images folder, including a trailing slash; related to {{{$account.path}}}.
!!!{{{logo}}}
If you have set a custom logo in your settings page, this generates a complete image tag to display it. If you have also set an account URL, it will be wrapped in a link to that URL.
!!!{{{logo_url}}}
If you have set a custom logo in your settings page, this will contain a URL pointing to it, ready for you to use in an HTML {{{img}}} tag..
!!!{{{haslogo}}}
A boolean value indicating whether you have uploaded a logo.
!!!{{{forecolour}}}
Your default foreground colour (as an HTML hex colour) as set on your branding page. Defaults to black ({{{#000000}}}). Also available as {{{forecolor}}} for our transatlantic brethren.
!!!{{{backcolour}}}
Your default background colour (as an HTML hex colour) as set on your branding page. Defaults to white ({{{#ffffff}}}). Also available as {{{backcolor}}} for our transatlantic brethren.
!!!{{{bodyfonts}}}
The CSS body font stack you have selected on your branding page. Defaults to an iOS-style "{{{'Helvetica Neue',Helvetica,Arial,sans-serif}}}" stack. Generally you will always need to add the {{{nofilter}}} keyword to prevent quoted values from being ~HTML-escaped.
!!!{{{headingfonts}}}
The CSS heading font stack you have selected on your branding page. Defaults to an iOS-style "{{{'Helvetica Neue',Helvetica,Arial,sans-serif}}}" stack. Generally you will always need to add the {{{nofilter}}} keyword to prevent quoted values from being ~HTML-escaped.
!!!{{{twitter}}}
Your twitter ID, as entered on the settings page. This includes the leading {{{@}}} symbol.
!!!{{{twitter_id}}}
Your twitter ID, as entered on the settings page. This ''DOES NOT'' include a leading {{{@}}} symbol.
!!!{{{twitter_pageurl}}}
The URL of your twitter home page.
!!!{{{twitter_follow}}}
This generates a javascript-based standard twitter follow button for web versions and previews, and a static link for email messages. See our social network function tags for more social networking tools.
!!!{{{linkedin}}}
Your ~LinkedIn ID, as entered on the settings page.
!!!{{{linkedin_pageurl}}}
The URL of your ~LinkedIn homepage.
!!!{{{googleplus}}}
Your Google Plus ID, as entered on the settings page.
!!!{{{googleplus_pageurl}}}
The URL of your Google Plus home page.
!!!{{{facebook}}}
Your Facebook ID, as entered on the settings page.
!!!{{{facebook_pageurl}}}
The URL of your Facebook home page.
!!!{{{vcard_url}}}
This URL points at a [[vCard|http://en.wikipedia.org/wiki/VCard]] holding your contact information. This is very useful when asking your subscribers to add you to their addresss books (which helps ensure inbox placement) as most modern systems will automatically add vCards to the main address book when opened. All the content in it is filled in using values from your account settings page. The vCard includes a logo if you've set one. On iPhone and iPad, this will return an [[iCal|http://en.wikipedia.org/wiki/ICalendar]] item, since iOS does not support vCard. You would typically add it to your template footer like this:
{{{
<a href="[[$account.vcard_url]]">Add us to your address book</a>
}}}
!!{{{$subscriber}}}
The subscriber array contains a large number of elements allowing you enormous power in personalising your messages for individual recipients. It's all dependent on actually having that data, so make sure you populate as many of the fields we support as you need to produce the personalisation you need – for example we can't address someone by their first name if you didn't provide their first name when you uploaded your list. Most of the values in these fields must be provided by you – for example we don't split first and last names apart if you only provide a full name in one field; we don't extract initials from the middles of names etc.
!!!{{{email}}}
The most fundamental thing in email marketing; the subscriber's email address.
!!!{{{informal_greeting}}}
This is a dynamic name that should be used to address or greet a subscriber. It checks various name properties and assembles the best greeting it can from the available data. This is a better option than trying to use a simplistic {{{[[$subscriber.firstname]]}}} as it is more likely to produce a usable result. The 'informal' part refers to the fact that it will attempt to build a greeting using the subscriber's first name.
!!!{{{formal_greeting}}}
Works the same way as {{{informal_greeting}}}, but attempts to build a more formal address like 'Mr Smith'. Here's a table showing how these two elements can appear and interaction with various input field possibilities and the {{{default}}} modifier:
|!Template tag |!Dear|!Title|!Firstname|!Lastname|!Output|!Notes |
|{{{[[$subscriber.informal_greeting]]}}}||||||No data, no default, no output|
|{{{[[$subscriber.informal_greeting|default:"Subscriber"]]}}}|||||Subscriber|No data|
|{{{[[$subscriber.informal_greeting|default:"Subscriber"]]}}}||Mr|John|Smith|John|Basic firstname|
|{{{[[$subscriber.formal_greeting|default:"Subscriber"]]}}}||Mr|John|Smith|Mr Smith|Basic title + lastname|
|{{{[[$subscriber.formal_greeting|default:"Subscriber"]]}}}|||John|Smith|Subscriber|Missing title|
|{{{[[$subscriber.informal_greeting|default:"Subscriber"]]}}}||Mr||Smith|Subscriber|Missing firstname|
|{{{[[$subscriber.formal_greeting|default:"Subscriber"]]}}}||Mr|John||Subscriber|Missing lastname|
|{{{[[$subscriber.informal_greeting|default:"Subscriber"]]}}}|Johnny|Mr|John|Smith|Johnny|Dear overrides firstname|
|{{{[[$subscriber.formal_greeting|default:"Subscriber"]]}}}|Johnny|Mr|John|Smith|Johnny|Dear overrides formal address|
!!!{{{title}}}
A salutation title, such as "Mr", "Dr", "Señora" etc.
!!!{{{initials}}}
If someone presents initials in their name, you should put them in here, so for "Joan P. User" you would expect this to contain 'P', or perhaps "J. P." – it's up to you.
!!!{{{firstname}}}
The subscriber's first name. Before you think of using this, look at the {{{informal_greeting}}} element which provides a more reliable means of addressing your subscribers by name.
!!!{{{lastname}}}
The subscriber's last or family name. Before you think of using this, look at the {{{formal_greeting}}} element which provides a more reliable means of addressing your subscribers by name.
!!!{{{dear}}}
This is a very useful field for greeting your subscribers. It's not uncommon for people to be addressed by names that are not made up of their title, first and last names. For example they might prefer a nickname or political title that is not related to their real name, for example a certain Mr Barack Obama might have a {{{dear}}} element containing "Mr President" which can be used to address him without having to take the foolish measure of setting his last name to "President"! In [[signup forms|Subscribing]] you might want to simplify the layout and use the {{{dear}}} field to capture a full name instead of having separate first and last name fields. See the {{{informal_greeting}}} and {{{formal_greeting}}} elements which provide a more reliable means of addressing your subscribers by name.
!!!{{{jobtitle}}}
The subscriber's job title.
!!!{{{companyname}}}
The name of the company the subscriber works for.
!!!{{{address1}}}, {{{address2}}}, {{{address3}}}, {{{posttown}}}, {{{county}}}, {{{postcode}}}
Three free-form address fields and other individual address elements. See the {{{address}}} element for a more reliable way of displaying a subscriber's address.
!!!{{{country}}}
The subscriber's country name, generated using standard [[ISO3166|http://www.iso.org/iso/country_codes.htm]] names in English.
!!!{{{countrycode}}}
The subscriber's [[ISO3166-1 alpha-2|http://en.wikipedia.org/wiki/ISO_3166-1_alpha-2]] country code, for example {{{GB}}} for the United Kingdom.
!!!{{{address}}}
A dynamically assembled concatenation of all the above address fields into a multi-line address, with blank lines left out. Use this with the {{{nl2br}}} and {{{stripbreaks}}} modifiers just as for {{{$account.address}}}.
!!!{{{phone}}}
The subscriber's phone number (land line).
!!!{{{mobile}}}
The subscriber's mobile number.
!!!{{{format}}}
It's possible for subscribers to set a choice of what format they want to receive messages in – either HTML or plain text. This will contain {{{html}}} or {{{plain}}} accordingly, defaulting to {{{html}}}. This isn't much use when you're already in an HTML or plain-text template context, but there's a remote possibility you might want this for something!
!!!{{{language}}}
The name of the subscriber's preferred [[ISO639-1|http://en.wikipedia.org/wiki/ISO_639-1]], in English. Defaults to {{{English}}}.
!!!{{{language_native}}}
The name of the subscriber's preferred [[ISO639-1|http://en.wikipedia.org/wiki/ISO_639-1]], in its own language – for example German would appear as 'Deutsch'. Defaults to {{{English}}}.
!!!{{{languagecode}}}
The [[ISO639-1|http://en.wikipedia.org/wiki/ISO_639-1]] of the subscriber's preferred language. See also the {{{languagename}}} and {{{languagename_native}}} modifiers.
!!!{{{dob}}}
Date of birth in ~ISO8601 format.
!!!{{{age}}}
The age of the subscriber in whole years. Relies on the {{{dob}}} property being populated. Defaults to 0 if {{{dob}}} is not set.
!!!{{{isbirthday}}}
{{{true}}} if it's the subscriber's birthday today (at the exact {{{$mailshot.sent_at}}} send time). Relies on the {{{dob}}} property being populated. Defaults to {{{false}}} if {{{dob}}} is not set. Example:
{{{
[[if $subscriber.isbirthday]]<p>🎂 Happy birthday! 🎉</p>[[/if]]
}}}
!!!{{{url}}}
A subscriber's URL, for example to their personal blog or ~LinkedIn page.
!!!{{{landingpage_url}}}
This points to the same page as {{{$account.landingpage_url}}}, but contains an additional identifier to pre-populate the page with data and subscription info for this specific subscriber.
!!!{{{custom1}}}...{{{custom32}}}
These are custom fields for you to use as you like. They are limited to 255 characters, but beyond that you can put what you like in them.
!!!{{{id}}}
A unique identifying hash – this is a random-looking jumble of about 20 letters and numbers that can be used to uniquely identify this subscriber. It's useful for inserting into ad tracking ~URLs and 'cachebusters'. All messages sent to this subscriber will have the same id value. See {{{$message.id}}} for a finer-grained identifier.
!!!{{{allow_tracking}}}
{{{true}}} if the subscriber has given consent for open and click tracking, {{{false}}} otherwise.
!!{{{$campaign}}}
A campaign is a folder in which related mailshots can be grouped.
!!!{{{id}}}
The ID of the campaign folder; a simple integer. This may be useful if you are feeding links into custom signup forms or our API and need to identify the campaign.
!!!{{{name}}}
Simply the name of the campaign folder.
!!{{{$mailinglist}}}
This represents the mailing list to which the mailshot is being sent.
!!!{{{id}}}
The ID of the list; a simple integer. This may be useful if you are feeding links into custom signup forms or our API and need to identify this mailing list.
!!!{{{name}}}
The name of the mailing list. On a mailing list page you can set two names for a list, one internal, one public. This element contains the public one.
!!!{{{description}}}
A description of this mailing list.
!!!{{{subscribe_url}}}
The URL of our standard signup form for this list.
!!!{{{subscriber_count}}}
The number of subscribers on this list.
!!{{{$mailshot}}}
Info concerning this particular mailshot. Note the mailshot does not have a {{{subject}}} property. While the subject is set at the mailshot level, it is itself a template, and may not contain usable text until it is merged with data relating to a particular subscriber and message, meaning the subject may be different for every message. For this reason you will find it in the {{{$message.subject}}} variable.
!!!{{{id}}}
Much like {{{$mailinglist.id}}}, an integer identifier for this mailshot.
!!!{{{name}}}
The name of this mailshot.
!!!{{{fromname}}}
The email account name this mailshot is sent from, for example "Marketing Manager".
!!!{{{fromaddress}}}
The email address this mailshot is sent from, for example "newsletters@example.net".
!!!{{{date_sent}}}
The date and time this mailshot (as a whole) was sent, in [[ISO8601 format|http://en.wikipedia.org/wiki/ISO_8601]], {{{yyyy-mm-dd hh:mm:ss}}}.
!!!{{{timestamp}}}
The date and time this mailshot (as a whole) was sent, in unix timestamp format. Format this into a more friendly representation with the {{{date_format}}} modifier.
!!!{{{unsubscribe_url}}}
This is an important element and ''must be present in your template'' – if your template does not contain this element, ''it will be inserted automatically'' as part of an unsubscribe link just before the closing {{{</body>}}} tag. An unsubscribe link would normally look like this:
{{{
<a href="[[$mailshot.unsubscribe_url]]">Unsubscribe</a>
}}}
Unsubscribe ~URLs will not work in web versions since they are generic and do not relate to any particular subscriber, hence they can't sensibly provide an unsubscribe link.
!!!{{{webversion_url}}}
All mailshots get an automatic web version that recipients can use to view your message if the message they received is unreadable or corrupt in some way (e.g. due to mail filter actions); this URL points to it. This is a generic version of your mailing and does not contain personal information (it uses placeholder data instead), so it's safe to share on social networks, forward to friends etc. For a personalised version, see {{{$message.webversion_url}}}.
!!!{{{previewimage_url}}}
This contains a URL of an image of this mailing, as used on the send page, so your message can contain a picture of itself! The image is generated to fit inside a 320x320 pixel square, though it may not fill the entire contents.
!!!{{{facebook_staticshareurl}}}
This is a URL used by Facebook to allow recipients to share the web version of this mailshot with their friends. You should build this into a link, and it does not require javascript.
!!!{{{linkedin_staticshareurl}}}
Like {{{facebook_staticshareurl}}}, but for ~LinkedIn.
!!!{{{twitter_staticshareurl}}}
Like {{{facebook_staticshareurl}}}, but for Twitter.
!!!{{{googleplus_staticshareurl}}}
Like {{{facebook_staticshareurl}}}, but for Google+.
!!{{{$message}}}
This holds properties of this individual message.
!!!{{{id}}}
A unique identifying hash – this is a random-looking jumble of about 16 letters and numbers that can be used to uniquely identify this individual message. It's useful for inserting into ad tracking ~URLs and 'cachebusters'. Every message will have a different value. See {{{$subscriber.id}}} for a coarser-grained identifier.
!!!{{{date_sent}}}
The date and time this message was sent, in [[ISO8601 format|http://en.wikipedia.org/wiki/ISO_8601]], {{{yyyy-mm-dd hh:mm:ss}}}.
!!!{{{timestamp}}}
The date and time this message was sent, in unix timestamp format. Format this into a more friendly representation with the {{{date_format}}} modifier.
!!!{{{tracking_url}}}
This a classic 'web bug' message opening tracker. It is a URL of a transparent 1-pixel GIF, and it allows us to be notified when a recipient opens a message. Your template must contain this in an image tag if it is to have message openings tracked. If you don't include this, a suitable image tag will be added automatically, but if you fnd that messes with your layout, you can add it yourself using this tag. A suitable tag would be:
{{{
<img src="[[$message.tracking_url]]" width="1" height="1" alt="*">
}}}
!!!{{{webversion_url}}}
This is just like {{{$mailshot.webversion_url}}}, but points to a fully-personalised web version of the message that was sent. Because this may contain personal information, we discourage the use of this URL as it is not suitable for public sharing and open access.
!!!{{{subject}}}
The subject of the message. Smartmessages subject lines are themselves complete templates – you can use nearly everything on this page in subject lines to generate them dynamically. Because of this, each message may have a different subject line, and this element will contain the one that this subscriber received. When this tag appears in a generic web version, it ends up blank, so we advise using a defaut modifier containing something that will work at the mailshot level or higher, for example:
{{{
<title>[[$message.subject|default:$account.name]]</title>
}}}
It's a good idea to set the title tag to the subject line like this as some spam filters mark you down if they do not match.
!!!{{{absplit}}}
While [[A/B Split Testing]] is driven by open rates, you can also make use of the decision in the body of your messages using this value. This property will have the value {{{a}}} or {{{b}}} depending on which split was chosen for the message. If your mailshot does not use an A/B split test, this property will default to {{{a}}}, so it's best to test like this:
{{{
[[if $message.absplit == "a"]]
Show this paragraph only to recipients in the 'A' group OR recipients sent this in an un-split mailshot.
[[else]]
Show this paragraph only to recipients in the 'B' group.
[[/if]]
}}}
!!!{{{ispersonal}}}
This boolean value is true when this message is personalised for a specific recipient, for example when it is sent as an email or viewed as a personalised web version (as opposed to the generic, unpersonalised default) You can use this in conditions to display content sections specific to those contexts, for example:
{{{
[[if $message.ispersonal]]
<p>Thanks for being a subscriber!</p>
[[else]]
<p>You can sign up to receive messages like this <a href="[[$mailinglist.subscribe_url]]">here</a></p>
[[/if]]
}}}
This would provide a signup link to anyone viewing the message as a web page rather than in their email.
!!{{{$subscription}}}
!!!{{{verified}}}
The verification status of this subscriber's membership of this list. If they have successfully completed a double-opt-in verification this will contain {{{yes}}}. If they have requested a double opt-in verification but have not yet clicked the activation link, it will contain {{{no}}}. If they have joined this list by some other means (e.g. from a list upload or by copying from another list), this will contain {{{n/a}}}.
!!!{{{date_added}}}
The date this subscriber was added to this list in ~ISO8601 format.
!!!{{{ip}}}
The IP address that this subscriber used when they completed their double opt-in, useful for confirming to a recipient that they did in fact complete this process!
!!!{{{reverification_url}}}
''WARNING'': Use of this tag is likely both unnecessary and illegal under both the 1996 Data Protection Directive and the 2016 General Data Protection Regulation. If your subscribers joined via our standard subscribe pages, or if you provided verification information when you uploaded your list, you do not need to ask for further consent since it is adequate under both the DPD and GDPR. If you don't already have sufficient consent to mail your subscribers, then mailing them to ask for more consent is also illegal. Please [[read the ICO's guidance on consent under the GDPR|https://iconewsblog.org.uk/2018/05/09/raising-the-bar-consent-under-the-gdpr/]] for more information.
This is a specially crafted URL that provides a shorter route to double-opt-in confirmation than sending new subscribers directly to a sign-up page. If you have subscribers on your list that have not completed a double-opt-in process, you should encourage them to click this link. If the subscriber //has// completed a double-opt-in, the URL will contain only a {{{#}}}. Here's a snippet that uses our {{{button}}} tag to create a button that will be shown only to subscribers that are not fully verified:
{{{
[[if $message.ispersonal and $subscription.verified != 'yes']]
Please verify your subscription by clicking this button:
[[button url=$subscription.reverification_url text="Verify now"]]
[[/if]]
}}}
The {{{if}}} tag it's wrapped in prevents the button being shown on web versions (which are not personalised), or to subscribers that //have// completed double-opt-in.
When a subscriber clicks this link, they will be sent a double-opt-in verification message containing a verification link, exactly as if they had submitted a subscribe page (in fact this link imlements the submission of the subscribe page, so it is exactly the same), and they will need to click that link to gain fully-verified status.
!Modifiers
As their name suggests, modifiers alter the output of tag in some useful way. There are [[many modifiers available|http://www.smarty.net/docs/en/language.modifiers.tpl]]. Modifiers are applied by using the pipe character ({{{|}}}) followed by the name of the modifier. Some modifiers can accept parameters which are added by appending a colon and the parameter values in single or double quotes (or a plain variable name).
If you use modifiers inside an HTML attribute, for example to apply URL escaping, it's important to use single quotes for the modifier parameters so that they do not get confused with the quotes used by the attribute itself, for example you'll have trouble with:
{{{
<a href="http://www.example.com/email=[[$subscriber.email|escape:"url"]]">
}}}
Do this instead:
{{{
<a href="http://www.example.com/email=[[$subscriber.email|escape:'url']]">
}}}
!!{{{default}}}
The default modifier substitues a default value in case the tag output is empty. For example if you address you subscriber like this:
{{{
Dear [[$subscriber.firstname]],
}}}
but your subscriber has no firstname stored, you'll end up with an uncomfortable-looking result:
{{{
Dear ,
}}}
The default modifier can solve this by substituting a default value, like this:
{{{
Dear [[$subscriber.firstname|default:"Subscriber"]],
}}}
which will render to this if the firstname field is empty:
{{{
Dear Subscriber,
}}}
You don't have to use literal text for the default value – you can use other variables too. For example something we often do is set the HTML title tag like this:
{{{
<title>[[$message.subject|default:$account.name]]</title>
}}}
The message subject doesn't exist for mailshot-level previews (because it can potentially be different for every recipient), so here we make it default to the account name instead.
!!{{{escape}}}
Escaping is treating certain characters specially so as to avoid breaking HTML or other markup scheme, and also as a security measure. Smartmessages automatically applies HTML escaping to all output fields, so generally you don't need to worry about this.
!!!Preventing escaping
There are situations where escaping is not wanted. For example, if you're including RSS content which contains pre-formatted HTML, you don't want it escaped or the HTML would not work. You can disable the automatic escaping using the {{{nofilter}}} keyword, like this:
{{{
[[$rssitem.contents nofilter]]
}}}
!!!Other escaping mechanisms
You might want to use a different escaping mechanism for other different contexts; the most common being to escape strings for safe inclusion in ~URLs, for example:
{{{
[["Is this a question?"|escape:"url"]]
}}}
would result in:
{{{
Is%20this%20a%20question%3F
}}}
which is safe to include in a URL.
Smarty provides [[other escaping mechanisms and additional parameters|http://www.smarty.net/docs/en/language.modifier.escape.tpl]].
!!{{{stripbreaks}}}
The stripbreaks modifier removes line breaks and replaces them with something else. This is especially useful for converting an unformatted multi-line full address into a formatted one. If your address is:
{{{
123 Station Road
Toytown
Toyland
TOY123
}}}
as plain HTML (using the {{{[[$account.address]]}}} template tag), that would appear like this, since HTML ignores line breaks:
{{{
123 Station Road Toytown Toyland TOY123
}}}
A better option would be to replace the breaks with commas and spaces:
{{{
[[$account.address|stripbreaks:", "]]
}}}
resulting in:
{{{
123 Station Road, Toytown, Toyland, TOY123
}}}
To keep the lines like the original text, you need to convert line breaks to HTML {{{<br>}}} tags, and there is a separate modifier for that, {{{nl2br}}} (short for "newline to br tag"). Since that modifier generates HTML, you also need to prevent escaping of the output:
{{{
[[$account.address|nl2br nofilter]]
}}}
!!{{{date_format}}}
This is a useful modifier for converting time formats, particularly from the unfriendly (but compact and efficient) unix timestamp format that we provide for message/mailshot send time. The parameter to this modifier describes various parts of the output time format and uses them for reformat the output as requested: for example {{{%Y}}} represents a 4-digit year, {{{%B}}} is the full month name etc. These special characters are defined in the [[PHP strftime function|http://www.php.net/strftime]]. Example:
{{{
This message was sent on [[$message.timestamp|date_format:"%A ,%e %B, %Y"]].
}}}
Will render to:
{{{
This message was sent on Monday, 26 May, 2014.
}}}
!!{{{date2age}}}
This is a simple modifier for converting a date string into an age in whole years. It's probably better to use the {{{$subscriber.isbirthday}}} and {{{$subscriber.age}}} properties if you're looking at subscriber properties, but this modifier can be used on arbirtrary date strings or date values stored in other fields. Renders to an empty string if the provided date is missing or not valid. Example:
{{{
You signed up to this list [[$subscription.date_added|date2age]] years ago.
}}}
Might render to:
{{{
You signed up to this list 2 years ago.
}}}
!!{{{languagename}}}
This converts an [[ISO-639-1|http://en.wikipedia.org/wiki/ISO_639-1]] language code into a language name in English. You may not need to use this because the language name is already available in {{{[[$subscriber.language]]}}}, but you may encounter language codes from other sources. Example:
{{{
You prefer to speak [[$subscriber.languagecode|languagename]].
}}}
Might render to:
{{{
You prefer to speak English.
}}}
!!{{{languagename_native}}}
This converts an [[ISO-639-1|http://en.wikipedia.org/wiki/ISO_639-1]] language code into a language name in its own language – for example 'Deutsch' in German, 'ελληνικά' in Greek. We don't have all language names converted, so some may default to English names. Example:
{{{
You prefer to speak [[$subscriber.languagecode|languagename_native]].
}}}
Might render to:
{{{
You prefer to speak ελληνικά.
}}}
!Function tags
Function tags provide dynamic output that cannot easily be provided by static field values. In addition to the [[standard functions that Smarty includes|http://www.smarty.net/docs/en/language.custom.functions.tpl]], Smartmessages provides some additional functions. Function tags accept parameters as space-separated pairs. Any modifiers you want to apply to the tag should appear immediately after the tag name, before the parameters.
!!{{{button}}}
It is messy and complicated to generate buttons in HTML that will work in email, so Smartmessages provides a tag that can generate them for you based on three popular online button generators. There are lots of options:
* {{{url}}}: a URL to link to; defaults to {{{$account.url}}}
* {{{text}}}: The button label; ''must be provided''
* {{{bg}}}: a background colour (CSS hex); defaults to {{{#333}}} (dark grey)
* {{{fg}}}: a foreground colour (CSS hex); defaults to {{{#fff}}} (white)
* {{{width}}}: width in pixels; defaults to 140.
* {{{height}}}: height in pixels; defaults to 40.
* {{{textsize}}}: font size in pixels; defaults to 13.
* {{{border}}}: border colour (CSS); defaults to no border.
* {{{radius}}}: Border radius in pixels; defaults to 0 (square corners)
* {{{fonts}}}: A CSS font stack to use for the button label; defaults to "'Helvetica Neue', Helvetica, Arial, sans-serif"
* {{{type}}}: 1 for [[buttons.cm|http://buttons.cm]] rendering; 2 for [[industrydive|http://www.industrydive.com/blog/how-to-make-html-email-buttons-that-rock/]]; 3 for [[Email on Acid|https://www.emailonacid.com/blog/article/email-development/bulletproof_buttons_for_office_365_and_everything_else]] (doesn't support {{{radius}}}); defaults to 1
Example:
{{{
[[button text="Visit our home page" bg="#e00" fg="#eee"]]
}}}
!!{{{facebook_like}}}
Facebook "Like" buttons are slightly complicated since they need to be different for web and email versions. This tag generates markup that works correctly in both contexts. It takes a single optional {{{url}}} parameter that defaults to the URL of the web version of the mailshot, but you can specify it manually so recipients can 'like' any URL you want.
!!{{{googleplus_share}}}
Much like a Facebook "Like" button, the google "+1" button the needs to be different in email and web versions, and again takes only a single optional {{{url}}} parameter that defaults to the URL of the web version of the mailshot.
!!{{{linkedin_share}}}
~LinkedIn's equivalent of a Facebook "Like" button, and again takes only a single optional {{{url}}} parameter that defaults to the URL of the web version of the mailshot.
!!{{{twitter_share}}}
Again like a Facebook "Like" button, and again takes only a single optional {{{url}}} parameter that defaults to the URL of the web version of the mailshot.
!!{{{twitter_follow}}}
Adds a Twitter "Follow" button using the Twitter ID set in your settings page.
!!{{{gravatar}}}
Gravatars are automatic icons generated from email addresses, [[documented here|Gravatars]]
!!{{{rss}}} and {{{simplerss}}}
The RSS tag is documented [[here|RSS]].
!!{{{toc}}}
This is the "table of contents" tag. This processes the finished output of your template and generates a list of intra-page links (that is, links that point at different areas of the same page, not other pages) in the form of nested HTML {{{<ul>}}} tags. Because it processes the finished template, it can include items generated from RSS feeds. It scans your template for HTML heading tags ({{{h1}}} to {{{h6}}}) and accepts several parameters to control the output:
* {{{start}}}: The heading level the TOC should start at; defaults to 1 for {{{h1}}}.
* {{{levels}}}: How many levels deep to go from the start level; defaults to 3 ({{{h1}}} to {{{h3}}}).
* {{{flat}}}: a boolean option – whether to generate a nested table of contents or a single-level flat structure; defaults to {{{false}}}.
* {{{container}}}: an HTML element {{{id}}} to restrict the scan to. If this is specified, the TOC will only be generated from heading tags occuring inside this element; defaults to empty (no restriction).
* {{{nolinks}}}: a boolean option – whether to omit links and just render headings as text; defaults to false (so links ''are'' generated).
Example: this would generate a 2-level TOC pointing at {{{h2}}} and {{{h3}}} tags in the entire document:
{{{
[[toc start=2 levels=2]]
}}}
This would generate a TOC of all {{{h1}}} items found inside an element with an {{{id}}} of {{{rss}}}:
{{{
[[toc container="rss" start=1 levels=1]]
}}}
It only includes heading tags that have an HTML {{{id}}} attribute set – otherwise they cannot be targeted, but if you have a heading tag that has an ID but you don't want it in the TOC, add the {{{notoc}}} class to its element, for example {{{<h3 id="someheading" class="notoc">Heading</h3>}}}, and it will be skipped.
!!{{{share}}}
In addition to service-specific tags for link sharing (such as {{{facebook_like}}}), Smartmessages includes a more general sharing tag that's not quite so clever, but supports many more services. It's called {{{share}}} and it takes the following parameters:
* {{{url}}} By default the URL of the mailshot's web version will be shared, but you can override it by providing a URL parameter.
* {{{on}}} A quoted, comma-delimited list of services to generate sharing links for. If you don't specify any, or specify {{{top}}}, only the top 5 sharing sites will be used. You can specify {{{all}}} to show links to all the all the links will be included (though that's quite a lot!). Dots, spaces, dashes and capitalisation are ignored, so for example 'delicious' and 'del.icio.us' are considered equivalent, and duplicates will be ignored. We have lots to choose from:
** Blinklist
** Del.icio.us
** Designfloat
** Digg
** Diigo
** ~DZone
** Facebook
** Folkd
** Google
** ~LinkedIn
** ~MisterWong
** ~MySpace
** Netvouz
** Newsvine
** Pinterest
** Reddit
** Slashdot
** ~StumbleUpon
** Technorati
** Twitter
** Webnews
** Yahoo
* {{{using}}} How the generated links should be displayed. The default is 'icons16x2', and the options are:
** {{{icons16}}} Display small 16-pixel icons.
** {{{icons16x2}}} Display small retina-ready 16-pixel icons.
** {{{icons32}}} Display larger 32-pixel icons.
** {{{icons32x2}}} Display larger retina-ready 32-pixel icons.
** {{{icons64}}} Display big 64-pixel icons.
** {{{links}}} Display text links in a line separated with {{{|}}} pipe characters.
* {{{title}}} The title to use when sharing, defaults to the message's subject line.
For example, this shares the mailshot's URL and subject line to Facebook, Digg and Pinterest using retina 32 pixel icons:
{{{
[[share using="icons32x2" on="facebook,digg,pinterest"]]
}}}
[IMG[images/share1.png]]
This shares the mailshot's URL and subject line to all services using retina 16px icons:
{{{
[[share on="all" using="icons16x2"]]
}}}
[IMG[images/share2.png]]
This shares the mailshot's URL and subject line to top services using 64px icons:
{{{
[[share using="icons64"]]
}}}
[IMG[images/share3.png]]
This shares your home page URL to top services using text links:
{{{
[[share url=$account.url using="links" title=$account.name]]
}}}
[IMG[images/share4.png]]
!!{{{history}}}
Displays a simple list of web version links to previous mailshots sent to the same list. This uses the name of the mailshot, not the subject line. Note that the list always includes the current mailshot.
Parameters to control the output:
* {{{count}}}: How many links to show. Defaults to 5. Set to 0 to include all mailshots ever sent to this list.
* {{{from}}}: Where to start the list from. If this is set to {{{this}}}, it will only show links to mailshots sent prior to this one. If set to {{{list}}} it will show links to the most recent mailshots to this list, even ones that occurred after the current one. For example if you send a monthly newsletter in May, {{{this}}} will always show links to the May, April, March, February and January newsletters; {{{list}}} will show the same list in May, but in the following December it would show links to more recent mailings sent to the same list since May. In short {{{this}}} will always show the same set of links for consistency; {{{list}}} will change to show the most recent ones. It defaults to {{{list}}}.
* {{{output}}}: a layout to use for the links. These are the same as the layouts used for the {{{simplerss}}} tag (see [[RSS]]). The options available are: {{{full}}}, {{{noshare}}}, {{{headlines}}}, {{{list}}} and {{{linear}}}. The {{{full}}} and {{{noshare}}} options include a thumbnail image. Defaults to {{{headlines}}}.
For example:
{{{
[[history]]
}}}
would result in the same output as:
{{{
[[history count=5 from="list" output="headlines"]]
}}}
!!{{{mimeicon}}}
Converts a MIME type such as {{{audio/mp3}}} into an icon. This is useful for formatting {{{$rssitem.enclosuretype}}} in RSS podcast attachments. You can see the icons that will be used in the library folder in the files tab, so you can use these icons anywhere else you like.
Parameters to control the output:
* {{{type}}}: The MIME type value or variable.
* {{{size}}}: Icon size to use. Supported sizes are 16, 32 and 128. The supplied icons are rendered at double resolution so that images look good on high-resolution (retina) screens.
!!!Example:
{{{
[[mimeicon type="audio/mp3" size=32]]
}}}
renders to:
[IMG[images/audio32.png]]
To format an {{{$rssitem.enclosuretype}}}, you would do this:
{{{
[[mimeicon type=$rssitem.enclosuretype size=32]]
}}}
If there is no enclosure in the {{{$rssitem}}}, this will simply render to nothing – you won't be left with a broken icon.
!!{{{translation_links}}}
Provides links to translate your web version into multiple languages using online translation services. Be warned that the translation services may add content around the page viewer, and the quality of translations is quite variable.
Parameters to control the output:
* {{{languages}}}: A comma-separated list of [[ISO639-1|http://en.wikipedia.org/wiki/ISO_639-1]] language codes, such as {{{en}}} for English, {{{fr}}} for French, {{{ru}}} for Russian etc. If you omit this parameter, it will generate a generic 'Translate' link text with no specified target language.
* {{{names}}}: What language to output language names in. Options are currently {{{english}}} to show language names in English, and {{{native}}} to show each language name in its own language.
* {{{output}}}: Simple layout options: {{{list}}} (the default) is a vertical list; {{{linear}}} is a horizontal line of links separated with pipe characters.
* {{{from}}}: We don't record what language a mailshot is in so we rely on the translation systems' ability to recognise the source language. If you want to tell the translation systems which language your mailshot is in, pass it in this parameter (as an ISO639-1 code). This will improve the accuracy of the source language selection, especially if you don't have much text.
* {{{provider}}}: Specify a translation provider. Options are {{{google}}} (the default) and {{{bing}}}. Other providers may be added in future.
If you want to use multiple providers (because some are better than others at particular languages), create multiple tags and split your target languages across them.
Note that translation links will not appear when previewing in the template editor because template previews are not accessible to the outside world; only mailshot web versions will work.
!!!Example:
{{{
Read this in [[translation_links languages="en,el,hy,ko,yi,ru" names="native"]]
}}}
Output:
[IMG[images/translate1.png]]
!!{{{video}}}
Please see our documentation on [[Video in email|Video]] for details.
!Block tags
!!{{{preheader}}}
Parameters to control the output:
* {{{limit}}}: the length to pad the preheader text to; defaults to 250 characters, and has a maximum of 1,000.
The preheader block tag is used to format text that will be displayed beside to the subject line in most mobile and web email client applications. This test is normally generated from the first readable text (i.e. not HTML markup) on the page, but that may not be what you want to show. The amount of text that is shown is limited and depends on screen size, so you usually want to keep this short, but there's a problem with that – most clients will display as much text as they can fit in, so they will keep scanning the message until the display area is full, which may contain more than you want. Fortunately there is [[a trick to control this|https://litmus.com/blog/the-little-known-preview-text-hack-you-may-want-to-use-in-every-email]], which is what this preheader tag handles for you. The trick is that it generates some invisible text content that is placed after your preheader, and that is used to displace any further text. This will mean that you can use a short preheader without other text ending up in there too. Preheader text will not be visible in the body of your message.
If your preheader text is longer than {{{limit}}}, no additional padding will be added. No processing is applied to plain-text templates; the content is displayed untouched.
''Important'': The preheader tag ''must be the first text content on your page''; otherwise other text will be displayed instead.
!!!Example:
{{{
[[preheader limit=100]]Read on for this week's thrilling instalment...[[/preheader]]
}}}
This will render to the rather cryptic but effective:
{{{
<div style="display: none; max-height: 0; overflow: hidden;">Read on for this week's thrilling instalment...</div><div style="display: none; max-height: 0; overflow: hidden;"> ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌</div>
}}}
Smartmessages has an enormously powerful templating system based on the popular [[Smarty templating framework|http://www.smarty.net]], and much of [[the documentation|http://www.smarty.net/docs/en/]] on that will apply to Smartmessages templates too.
!Literal text
The majority of a template is made up of straight HTML or plain text that is left untouched. Variables, modifiers and other tags may be used to add, substitute or alter parts of the template in order to render it into a complete message destined for an individual recipient.
!Tags
A tag is a dynamic element that will render to some useful value, such as the recipient's name, when each message is generated. Tags are delimited by {{{[[}}} and {{{]]}}} to distinguish them from literal text, so a typical tag will look something like {{{[[thisisatag]]}}}. You can only use tags that are defined – using non-existent tags will result in an error and you won't be able to send your mailshot; all the tags we support are listed in the template guide.
!!Block Tags
Most tags are just single tags like {{{[[thisisatag]]}}}, but some are made up of two elements, with an opening and closing tag. Just like HTML tags, these are differentiated with a {{{/}}} at the start of the name of the closing tag, and you can put content and other tags between the opening and closing tags, for example:
{{{
[[thisisatag]]This mailshot is called [[$mailshot.name]][[/thisisatag]]
}}}
Tread creafuly though – an opening tag without a corresponding closing tag is invalid, and your template won't work. Examples of block tags include {{{[[if]]}}}, {{{[[rss]]}}}, and {{{[[preheader]]}}}.
!Variables
Smartmessages provides several useful variables that are actually arrays of multiple items. These allow us to group related items together in a consistent way. Variables are denoted by a {{{$}}} sign at the start of their name, for example {{{$account}}} is the variable which contains items relating to your Smartmessages account. Individual elements within an array variable are accessed by name, so the name of your account can be found in {{{$account.name}}}, and a complete tag that will render to your account name would be {{{[[$account.name]]}}}. Variables are most often used in plain tags when you just want to display their value, but you can also use them in other places, such as in conditions (see below). You'll find a complete listing of variables and the elements they contain in [[the template guide|TemplateGuide]].
!Modifiers
As their name suggests, modifiers are applied to variable values in order to change them in same way as the template is rendered. A typical modifier might be {{{upper}}}, which converts the value to upper case letters. Modifiers are applied using the pipe character: {{{|}}} followed by the modifier name and are placed after whatever they are modifying, so to capitalise your account name you could say: {{{[[$account.name|upper]]}}}. Some modifiers can be given parameters to change their behaviour; these are provided by following the modifier name with a colon, then the parameters in double quotes. For example the {{{escape}}} modifier applies HTML escaping by default, but it can be switched to other forms of escaping via a parameter; {{{[[$account.name|escape:"url"]]}}} will apply URL escaping, useful for inserting un-encoded values into ~URLs safely. Multiple modifiers can be chained one after the other, so to capitalise AND apply URL escaping to your account name you would say {{{[[$account.name|upper|escape:"url"]]}}}. You can apply modifiers to literal text by putting the text in a tag like this: {{{[["this is some text"|upper]]}}} and it will process the literal text just like it does for variables. Some native PHP functions can also be used as modifiers, for example
There's a full list of available modifiers in the template guide.
!Function tags
Smartmessages provides some special function tags to produce dynamic content in a much more compact form than is possible with simple strings. For example, you can create a fully operational Facebook 'Like' button simply by saying {{{[[facebook_like]]}}}. Much like modifiers, function tags can often accept parameters, for example the {{{[[gravatar]]}}} function tag accepts optional {{{size}}}, {{{email}}}, {{{rating}}} and {{{default}}} parameters to change its output. The full list of these special tags is in the template guide.
!Complex tags
There are some tags that have higher levels of complexity. The most useful of these is the RSS tag, which allows you to render RSS feeds dynamically in your templates. This can save an awful lot of cutting and pasting if you have, for example, a company blog that you want to republish stories from in your mailshots. There is [[complete documentation on the RSS tag|RSS]].
!Conditions
Conditions are a kind of control structure that allows you to show or not show sections of your template to your recipients based on any value you like, and they are an important feature for personalisation. Conditions are built with the {{{if}}} tag. They are a bit more complex than simple tags because they have a opening and a closing tag – every opening {{{[[if]]}}} tag must have a matching closing {{{[[/if]]}}} tag. Here's a simple example:
{{{
[[if $subscriber.firstname == 'Bob']]
Wow! You're called Bob! That means you get to see this secret paragraph!
[[/if]]
}}}
You can see the {{{[[if]]}}} tag is inspecting the value of {{{$subscriber.firstname}}} to see if it is equal to 'Bob' (notice that it uses //two equals signs//, not just one), and if it is, it will show the content that occurs between the opening and closing tags, and people who are not called Bob will not see it. You can inspect any value provided in the variables, and use many operators and functions on the compared values. {{{[[if]]}}} has some further tricks up its sleeve in the form of {{{else}}} and {{{elseif}}} tags. The else tag allows you to say what to do if something does //not// match what the {{{if}}} tag checks for, for example:
{{{
[[if $subscriber.firstname == 'Bob']]
Wow! You're called Bob! That means you get to see this secret paragraph!
[[else]]
Have you considered changing your name to Bob?
[[/if]]
}}}
{{{elseif}}} allows you to check for further conditions before giving up:
{{{
[[if $subscriber.firstname == 'Bob']]
Wow! You're called Bob! That means you get to see this secret paragraph!
[[elseif $subscriber.firstname == 'Carol']]
Yay, you're in the Carol club!
[[else]]
Have you considered changing your name to Bob or Carol?
[[/if]]
}}}
Here people called Bob will see the first paragraph, people called Carol will see the second, and everyone else will see the third (but Bob and Carol will not see the third).
!!Nesting
You can also nest these structures one inside the other, but make sure you close tags in the right order or you'll get a template error:
{{{
[[if $subscriber.firstname == 'Bob']]
Wow! You're called Bob! That means you get to see this secret paragraph!
[[if $subscriber.lastname == "Smith"]]
Surely not <em>the</em> Bob Smith??
[[/if]]
[[/if]]
}}}
!!Operators
When doing your comparisons there are several useful operators to choose from:
|!Operator|!Meaning|
| {{{==}}} |Equal to|
| {{{!=}}} |Not equal to|
| {{{>}}} |Greater than|
| {{{<}}} |Less than|
| {{{>=}}} |Greater than or equal to|
| {{{<=}}} |Less than or equal to|
You can also use logical operators to compare multiple values at once, for example:
{{{
[[if $subscriber.firstname == 'Bob' and $subscriber.lastname == "Smith"]]
Wow! You're called Bob Smith!
[[/if]]
}}}
Available logical operators include {{{and}}}, {{{or}}}, {{{not}}} and others, and they can be grouped and isolated using parentheses (round brackets), for example:
{{{
[[if ($subscriber.firstname == 'Bob' or $subscriber.firstname == 'Carol') and $subscriber.lastname == "Smith"]]
Wow! You're from the Smith family!
[[/if]]
}}}
!Mathematicical operations
You're not limited to text processing – you can do mathematical operations too, for example if you have put a product price in the {{{$subscriber.custom1}}} property you could do this:
{{{
Regular price £[[$subscriber.custom1]], your special discount price only £[[$subscriber.custom1*0.8]]!!!
}}}
You can use or apply mathematical operations pretty much anywhere it's appropriate, including by themselves, e.g. {{{[[2+2]]}}}
!PHP Functions
Many native PHP functions can also be used inside tags either in calculating conditions or mathematical operations, or as modifers, for example {{{[["Hello"|strtolower]]}}} will result in "hello".
We offer complete support for user-uploadable templates, so you can paste in your HTML, grab it from a web page, upload a file, or insert it via our API. Templates can make use of all of our dynamic features. We support template syntax used by other popular ~ESPs, so we can even translate tags for you.
//You don't necessarily need to create your own templates. Our standard templates provide straightforward WYSIWGYG editing without any HTML knowledge required. You only need to use this feature if you're familiar with HTML for email and want to code your own.//
!!Templates are starting points
When you create a mailshot you can choose a template as a starting point. When you do that it copies the contents of the template into the mailshot, and from that point on you can edit it independently – changes you make in a mailshot will not be copied back into the original template, so you can reuse the same template over and over. Correspondingly, if you edit a template after copying it into a mailshot, the mailshot will not be changed – though you can always reselect the template to copy it again.
!!The templates page
The templates tab allows you to add a new template, then add your contents. You can provide both HTML and plain-text versions, which you can grab from ~URLs if you happen to have posted your templates on a web server somewhere, though be aware that the web and email are really quite different, and most web pages will not work well as emails.
You'll see a list of your templates (which will initially be empty) on the left hand side – click the 'Add' button below the list to create a new template.
Each template has a title which will appear in menus and informational screens, such as when sending a mailshot. The description is used in the template gallery to provide a longer description of that particular template's features or purpose.
The subject line is a default and may be overridden on the send page. Subject lines are fully dynamic templates too; you can use the same [[template tags|TemplateGuide]] in the subject as in plain text bodies.
At the top of the page you'll see indicators of the current save state of the template, and whether it has encountered any errors in the template. Templates are checked for errors whenever you save them, and you can't send mailshots using templates containing errors.
[IMG[images/templatespage1.png]]
!!Editing a template
As stated above, the HTML editor is for those who like to get their hands dirty with HTML – if that's not your cup of tea, you don't need to use this page at all.
Still here? Good; you'll need to know what you can do here! The HTML editor is a plain text box into which you can paste your HTML code, or import it from an external URL (e.g. from an external template building service). When you create a template we generate a bare-bones HTML containing the minimum you need to get going. Above the editor you'll see a tag menu; from this you can select any of the placeholder fields and dynamic tags that we provide – we thoroughly recommend you make use of these as they can save you a lot of typing and help avoid mistakes. Just put your cursor where you want the tag to go, select the tag for the menu and click 'Insert field' and it will insert it at that point. You can read [[full details of our template syntax|TemplateSyntax]].
[IMG[images/templatespage2.png]]
Down at the bottom of this pane are some innocuous-looking but powerful checkboxes that make migrating templates from other systems incredibly easy.
!!!Convert CSS to inline when sending
We have [[more details on this topic|CSS Inlining]], but the short version is that this converts a CSS style sheet into inline style tags, which may help your styling work in low-quality renderers liek gmail an Outlook. Checking it here doesn't do anything immediate, but it means that when you select this template on the send page, the send-time option will be selected automatically. Note that this ''only'' applies to sending email messages; styles are not inlined in previews or web versions, as it's unnecessary there.
!!!Import Images
If you paste in a template that has been created elsewhere and contains links to images, you can check the ''Import images'' checkbox and then when the template is saved, all the referenced images will be fetched into Smartmessages (they will appear in the Files tab), and the ~URLs pointing at them will be rewritten to point at our copies.
In this process, image tags like this:
{{{
<img src="http://www.example.com/logo.jpg" width="200" height="100" alt="Example.com logo">
}}}
will be converted to tags like this:
{{{
<img src="/images/logo.jpg" width="200" height="100" alt="Example.com logo">
}}}
These are relative ~URLs, which makes editing and moving templates between systems much simpler, but they will be converted to absolute ~URLs when your messages are sent so that they work correctly in remote email clients.
If you want to prevent a particular image from being imported and its URL converted by this operation, add a {{{nosmimport}}} attribute to your image tag like this, and it will be left alone:
{{{
<img src="http://www.example.com/logo.jpg" width="200" height="100" alt="Example.com logo" nosmimport>
}}}
!!!Convert template format
This is an awesome feature! Because our templating system is so powerful and flexible, we have little difficulty in converting templates from other systems to work in Smartmessages. All you need to do is paste in your template (copied from another system), check this box, hit save and it will detect the source format and convert the template into our format. You can combine this with the image import function at the same time. At present we can convert from [[our old template syntax|New Template Conversion]], Mailchimp and Eshot formats. If you want us to support another format, just ask us and ideally provide us with a link to technical documentation, and we'll see what we can do.
While the template //format// conversions may be fairly complete, we may not support all the //features// of the origin system. For example Mailchimp has a loyalty point system that is specific to them, so there's no point in us supporting that – correspondingly we have features that other formats don't have, so you can't expect to make use of them from another system's template format. Where we don't have an exact equivalent feature we substitute our nearest equivalent, or if we can't do that we remove the tags.
!!Importing from a file
At the bottom of the template settings panel you'll see an "Import template from file" selector; you can either click that and select the file, or drag & drop a file onto it, then click save. We support several options here:
* Simple HTML files, saved with a {{{.html}}} or {{{.htm}}} extension
* Simple plain-text files, saved with a {{{.txt}}} extension
* Templates saved as a zip archive (using a {{{.zip}}} extension
If you import using any of these formats it will overwrite whatever you may already have in the HTML and plain-text boxes, and format conversions are applied automatically. For plain-text imports, it checks inside the file to see if it's actually HTML saved with the wrong extension. When you provide a {{{.html}}} file, we automatically generate a plain-text version of the template for you. Zip files are a little more complex; these are typically arranged like this:
[IMG[images/templatezip.png]]
At the top level of the zip file is an HTML file, optionally also a plain-text .txt file, and a folder containing images that are referenced using reative ~URLs from within the HTML, so in this example the HTML might refer to an image at {{{images/kittens1.jpg}}}. The importer spots these references and imports all the images for you, but it creates a folder using the name of the template, puts the images in there, and rewrites the ~URLs to point there. This avoids overwriting existing images used in other templates. Templates may also refer to images that are //not// included in the images folder, and it will leave them untouched; images using absolute ~URLs will also be converted if you enable the "import images" checkbox on the HTML tab. If you forget to do that, you can always do it afterwards. For example, if an original image tag looked like this:
{{{
<img src="images/kittens1.jpg" width="200" height="100" alt="Kittens!">
}}}
It will be converted to something like this:
{{{
<img src="/images/my-template-name/kittens1.jpg" width="200" height="100" alt="Kittens!">
}}}
You will be able to see images that you have imported this way in the main files tab – look for the folder name.
!!Checking your template
We've said many times that it's vitally important to test your templates. As well as simply sending yourself test mailings, we provide several useful tools for checking your templates and mailshots. When your template has been saved and is passing a syntax check (there's no point in testing a template you know is broken!), you can select options from the menu attached to the preview button:
[IMG[images/templatespage3.png]]
The preview button itself renders a straightforward view of the message. The other options do much more:
* Preview (Images off) – This shows the same view as the normal preview, but with images replaced with placeholders. This is similar to what recipients will see if they have images disabled, which is the default for most email clients.
* Preview (Plain text) – A straightforward preview of the plain-text version of your template.
* Preview (mobile) – The same as the normal preview, but shown in a window the equivalent size of an Apple iPhone 5, so you can test responsive layouts, small-screen usability and so on.
* Validate – Checks your template using the ~W3C's HTML validator. While strict validity may not be necessary, this is a great way to spot simple mistakes such as unclosed or misnested tags, missing {{{alt}}} attributes etc.
* Link report – Follows all the links in your template and makes sure they return sensible results, reporting any errors.
* Image report – Loads and inspects every referenced image and HTML image tag – this spots missing or corrupt images, incorrect file types, mismatched dimensions, excessive file sizes and more.
* Spam report – Runs your message through the standard ~SpamAssassin spam filter to check how 'spammy' it looks. This report also includes our own appraisal of your message, such as spotting MS Word leftovers (Pleeeeease don't use Word for generating HTML!), excessive size and more.
A template provides the overall look and layout of the content of the messages you send through Smartmessages.
Out of the box, we provide some standard basic templates for a blank message (you provide all content), a simple note, an invitation to an event, and a newsletter. These are ready to roll, and if you have paid for our account setup service, you'll find these automatically make use of your custom headers and footers. Each template can contain multiple editable elements – a simple note has a single content area, but a newsletter has four, and the send page will automatically show the options to match the template.
These templates also include a plain text version, an automatic link to a web version (for those who can't or have trouble receiving HTML email), a link to subscription options (unsubscribe etc), and an opening tracking image.
!!What's special about Smartmessages templates?
The big difference between our templates and those of most other providers is that they can be reused. Instead of having a designer create a new template for you every month, you can get them to do it just once, and then you can just change the content every month without having to go back to your designer every time. We feel that anything less doesn't really justify the name 'template' – why go to all that effort and testing for a single mailing?
We can build custom templates for you from scratch, or you can provide us with your version and we can adapt it for you, or you can do it all yourself through our [[templates|TemplateUploads]] page.
!!Creating your own templates
If you're creating your own templates using our templates page, there are some things you need to be aware of when designing HTML for email.
!!!Email is not the web
Many people forget this and expect HTML email to act just like a web page. It won't. Here are some things you need to look out for:
* ''Old-school HTML 4 rules''. With the recent ravages of MS Outlook 2007, CSS in email is now mainly a recipe for disaster. While there are still ways you can use it, it's so convoluted to make it work reliably that it's not really worth the hassle. This means that you should dust off those old articles about sliced images, tables for layout and font tags – they are the only things that work reliably and easily. Email now is like the web was in 1997.
* ''All ~URLs must be absolute'' – if your links or images don't start with 'http', they are probably wrong. On a web page these ~URLs are considered relative to the current page, but when you're looking at an email, the message doesn't have a URL, so those ~URLs will not work.
* ''No external resources'' – that means no external scripts or style sheets.
* ''Don't use the <base> tag'' – it can work, but will also break in some clients (hotmail), and will prevent you from using intra-page links (href="#...").
* ''No text over images''. One of Outlook 2007's most heinous acts is to make it impossible to place text on top of images because table cell backgrounds don't work in it.
* ''Web pages are not email messages''. The majority of web pages presented directly as emails simply won't work, so don't expect them to.
* ''Imported templates are filtered'' before use. If we didn't filter javascript and various other aspects, we could become a vector for [[XSS attacks|http://en.wikipedia.org/wiki/Cross-site_scripting]].
In order to work within these restrictions, we have some other suggestions which are mainly just good practice for web, email and informational design:
* ''Use our checkers'' – On the template and send pages you'll find a whole array of tools to check your links, images markup and spam rating – ''Use them!''
* ''Use our relative image links'' – If we are serving your images, you can use relative ~URLs (such as {{{/images/logo.png}}}) and we will automatically rewrite them to absolute ~URLs for you, making them much easier to work with.
* ''Validate your HTML'': Invalid HTML is just wrong, no exceptions – if you have cross-client layout problems, check the HTML is valid first – Use the validation link in our template editor, or alternatively the [[Total Validator|https://addons.mozilla.org/firefox/addon/2318]] plugin for Firefox is a good tool for this, or paste a rendered message (our web preview is a good source for this) into the [[W3C validator|http://validator.w3.org/]].
* Make sure your message remains meaningful and legible with images disabled since that's the default in the majority of email clients. //Always// use alt attributes on your images, and make them meaningful as they often displayed when images are off. Our template editor has a 'preview without images' link for testing how this looks.
* ''Check your content'': We provide link and image testing options in the template editor, which will tell you about broken links, missing, misformatted or mis-sized images. We also provide a ~SpamAssassin-based spam checker and some simple tests against our own set of useful rules.
* ''Keep it simple'' – email clients are not modern browsers; keep your stories short and messages clear, link to more complex content (clicks are your marketing intelligence goldmine). Smaller, simpler messages send faster, bounce less, open faster, dilute recipients precious attention less.
* Provide a plain text version of your template – some users //like// living in the last century...
* Use background colours to add colour to your messages when there are no images.
* ''TEST, TEST, TEST'' in all email clients you expect your message to be read in – you'll probably need yahoo, hotmail, gmail accounts, and Outlook 2003, Outlook 2007, Apple Mail, Eudora, Evolution and Thunderbird desktop clients. Alternatively, use a service like [[Litmus|http://www.litmusapp.com]] for cross-client testing.
* You don't have to do anything special to get your links tracked – just leave them as they are. You can also [[suppress link tracking|Link Tracking]] on a per-link basis.
* To insert dynamic data within your templates, use the macros available in the template editor pop-up.
* If you stick to straightforward HTML with no javascript and no external references (other than images), you shouldn't run into any issues with filtering.
!![[The Daily Telegraph|http://www.telegraph.co.uk/]]
We recently undertook a data protection and list cleaning exercise for the Daily Telegraph for their list of two million readers.
!!Daily Telegraph Fantasy Football
We ran last season's fantasy football mailings to their list of 200,000.
!![[Guitar Amp & Keyboard|http://www.guitarampkeyboard.com/]]
One of Europe's biggest music retailers, we handle their list of 140,000
!![[Woolovers|http://www.woolovers.com/]]
A rapidly-growing business that's getting great results:
//"The broadcast of the email started at just after 9pm last night finishing around 10.45pm.
Number of sales for both today and yesterday 142 & 102 just for today. If you look at the same time period for last week we only had 31 orders for the two days. A big success so far. Let's see how many more orders flow through over the weekend. A big thank you to all of you for the help you gave me in setting up this fantastic marketing tool."//
Unsubscribing is the act of removing a subscriber from a mailing list. This could be accomplished by clicking a link, submitting a web form, sending an email to a special address, calling an [[API]] or some combination of those actions. By default, Smartmessages provides a simple unsubscribe form that's linked from every message we send, so you don't need to do anything in order to have full unsubscribe handling.
!!Why support unsubscribes?
You might think that the last thing you want is to make it easy for someone to get off your list, but there are major advantages (quite apart from your legal obligations) to doing so. Put it like this – every time someone unsubscribes, the quality of your list goes up; it contains proportionally less people that don't want to hear from you and more that do. If you persist in sending messages to someone that doesn't want them, they will most probably [[report your message as spam|SpamReports]], which can reduce the deliverability of ALL your other messages, or even get you blacklisted/blocked in the worst case. That's not good. As well as being illegal in many countries, it's also not polite, so do what your subscribers ask.
To comply with data protection laws, including the US ~CAN-SPAM act, It's vital that every message sent to a list includes an unsubscribe link. We always process unsubscribes immediately – if you have a mailshot scheduled to send and someone unsubscribes 1 second before it is sent, they will not be mailed, which also exceeds the requirements of ~CAN-SPAM.
All our standard templates include an unsubscribe link, and you can add one to your own templates in our [[template editor|TemplateUploads]] – if you don't add one, we'll put one in automatically since it's a legal requirement.
!!Standards support
Because links can sometimes go astray or become corrupted within the body of a message by mail/spam filters, we include something called a "~List-Unsubscribe" header in every message, as described [[here|http://www.list-unsubscribe.com/]] and in the [[RFC 2369|http://www.faqs.org/rfcs/rfc2369.html]] standard. These provide a simple and consistent way for subscribers to remove themselves from your lists, are much more likely to make it through filters intact, and are supported by an increasing number of the major email services, most notably Windows Live Mail, Gmail and Yahoo!
!!Who has unsubscribed?
You can get a list of users that have unsubscribed from each of your lists on our contacts page – just click the 'Download Unsubscribes' button to get a simple CSV format list. If you maintain a list of subscribers outside of Smartmessages, you can use that list to remove those that have unsubscribed.
When someone unsubscribes from a list, we automatically [[suppress|SuppressionLists]] them from uploads to that list so that they do not get inadvertently re-subscribed against their wishes.
!!Unsubscribe links in your templates
When you save a template, we apply some automatic filters and checks, and the unsubscribe link is one of the things we look for. We look for ''exactly'' this string:
{{{
<a href="[[$mailshot.unsubscribe_url]]"
}}}
and if your template doesn't contain that, we add an unsubscribe link automatically. If you find that you get a second unsubscribe link added, you may have something that doesn't quite match it, for example this would not match because the {{{href}}} attribute does not appear first:
{{{
<a style="color: blue" href="[[$mailshot.unsubscribe_url]]">unsubscribe</a>
}}}
but this would be OK:
{{{
<a href="[[$mailshot.unsubscribe_url]]" style="color: blue">unsubscribe</a>
}}}
!!Unsubscribe processing options
There are several options available for handling unsubscribes in Smartmessages:
*Use our standard unsubscribe links and forms
*Use our standard link and forms customised with with your own [[branding|Branding]]
*Build your own unsubscribe form (see below for details) and let us process it
*Build your own form, process it youself (for example so you can add an unsubscribe survey), and notify us of the unsubscribe via our form processor or an API call.
!!Custom unsubscribe forms
In a similar way to [[automating subscribes|Subscribing]], you can automate our unsubscribe forms too. Many of our customers want to use their own web forms to submit information to our unsubscribe processor, and that's also easy to do – just point your form's action at https://www.smartmessages.net/unsubscribe.php. This approach is much simpler than using our API.
The form processor can make use of the following parameters (bold fields are required):
*''//command//'' – the value 'unsubscribe'
*''//emailaddress//'' – the email address of the new subscriber
*''//mlid//'' – the ID of the mailing list they are unsubscribing from (this is the value that's visible in the "link" links on the contacts page)
*//redirect// – a URL to go to after processing the subscription request instead of displaying our own default page (don't forget to ~URL-encode it)
*//json// – any value – its presence will indicate that you want a response in a JSON format (e.g. you're unsubscribing from ~Javascript)
By building your own form and providing a redirect URL, you can use our unsubscribe processor completely transparently and invisibly to your users. If you specify a redirect URL, you will receive an HTTP GET request to that URL containing your submitted parameters (so you can process it further – for example remove it from your own contact database) along with additional information about the success (or not) of the subscription request in a 'statuscode' parameter. This has the following meanings:
*1 – Success
*3 – Mailing list not found
*5 – Missing required parameters
*6 – Already unsubscribed
*7 – Already globally unsubscribed
*8 – Placeholder link followed
*9 – Invalid email address
The JSON output also includes a 'success' value that is true for codes 1, 6 and 7, false for others, along with a 'message' value containing a plain-text explanation of the response.
Here's a minimal example form that you can adapt:
{{{
<form action="https://www.smartmessages.net/unsubscribe.php" method="post">
<p>
<input type="hidden" name="command" value="unsubscribe" />
<input type="hidden" name="mlid" value="<insert your mailing list ID here>" />
Email address: <input type="text" name="emailaddress" />
<input type="submit" name="Unsubscribe" />
</p>
</form>
}}}
Note that if your account has global unsubscribes turned on, it doesn't matter which mailing list ID you use, so long as it's one of yours.
!!Further automation
It's possible to change the ordering of this process. If you handle the request yourself, you can then make a behind-the-scenes request to our processor to tell us about it. We recommend that you make use of the {{{json}}} parameter in that case as it will provide the quickest and simplest response.
To upload a list click on the ''contacts'' tab. [IMG[images/contacts.gif]]
Choose the ''Manage'' button next to the list you want to upload into: [IMG[images/manage.gif]]
Click the ''Actions'' tab:
[IMG[images/upload.gif]]
Choose the ''Upload a list'' tab
[IMG[images/upload2.gif]]
When uploading a list there are some options.
!!Source
It's important to be able to keep track of where the email addresses in your account came from, so when you fill this field in, anyone who is added to a list will have this note attached to their history.
!!Overwrite existing data
When you add someone to a list, there are three scenarios:
* They are already on this list
* They are not on this list, but they are on other lists of yours, or have been in the past
* They are new, and you've never seen them before
The first case is simple – we do nothing, leaving their data untouched. In the second case we add them to this list, but don't touch any of their other data. In the third case, we simply add all the data you upload attached to the new address.
Now imagine that the data that is already in the system is wrong, or outdated and you want to replace what's there. For example if you have live data in custom fields that is used every week, you would want to check this box, similarly if you uploaded data that was incorrect (e.g. you got firstname and lastname the wrong way around).
!!Replace existing list
Normally a list upload only adds to a list. If you check this box, anyone not included in the list you upload will be removed. So if there are 10,000 subscribers on this list and you upload a list of 10 new ones and check this box, you will end up with a list with only 10 people on it – so tread carefully!
!!First line contains field names
Checking this box means that the import expects the first line of the CSV file to be a list of the column names, such as first name, email address, etc
!!Upload history
Lists are uploaded from a queue, so the upload history gives feedback of the status and once uploaded, information on the list.
[IMG[images/uphistory.gif]]
Roll over the column names on the live system to have an explanation of the finer detail.
Video in email is a very popular thing to try, but is fraught with difficulties.
Generally only Apple platforms can play video in email clients; Apple Mail on OS X and Mail on iOS both have excellent video support; almost nothing else does. Many commercial video services, in particular ~YouTube and Vimeo, prohibit direct embedding of video files in their terms of service – you are only permitted to embed javascript or Flash players. Since neither of those technologies work in email, it's only possible (and legal) to show a placeholder image linked to the site's own page. If you want to show video that plays directly inside your message on supported platforms, the best approach is to host the clip on your own site. Because of these limitations, you should not rely on video working in your messages, and restrict your movies to small, low-bandwidth clips such as simple animations, screen recordings and "talking heads".
!!The {{{video}}} tag
We support video in email using the {{{video}}} function tag.
When you include a video tag in your template, Smartmessages will automatically add some CSS rules to your {{{<head>}}} tag that help it behave better on platforms that do not support video well, such as Android and Windows.
If you only intend to use ~YouTube for your clips, this tag results in essentially the same output as using a simple image (which it will find for you) with a link pointing at the movie page.
Parameters to control the output:
* {{{url}}}: The MIME type value or variable.
* {{{image}}}: A URL of a fallback image for clients not capable of showing ~HTML5 video tags. If you don't provide an image URL, a generic placeholder image will be used instead (from our image library). If your clip is from ~YouTube or Vimeo, preview images are obtained automatically from the URL, so you can leave this unset.
* {{{width}}}: The width of the movie in pixels. Defaults to 400.
* {{{height}}} The height of the movie in pixels. Defaults to 225, or calculates a 16:9 aspect ratio (standard wide-screen) height from the width if only the width is specified.
* {{{alt}}}: The content of the {{{alt}}} and {{{title}}} attributes. This text may be shown if images are disabled. Defaults to a generic "Video clip" string.
* {{{controls}}}: Control the visibility of the video playback controller bar. Defaults to {{{true}}}; set to {{{false}}} to hide the video player control bar, though beware that this may make the video unplayable in some clients! This is automatically hidden if you've supplied a ~YouTube or Vimeo URL as they will display an unplayable fallback image anyway.
!!!Example
{{{
[[video url="http://mirror.cessen.com/blender.org/peach/trailer/trailer_iphone.m4v" image="http://sandbox.thewikies.com/vfe-generator/images/big-buck-bunny_poster.jpg" width=400 height=225 alt="Big Buck Bunny"]]
}}}
[IMG[images/videoplay.jpg]]
Example content from Big Buck Bunny © Copyright 2008, Blender Foundation / [[www.bigbuckbunny.org|http://www.bigbuckbunny.org]]
<!--{{{-->
<div class='toolbar' role='navigation' macro='toolbar [[ToolbarCommands::ViewToolbar]]'></div>
<div class='title' macro='view title'></div>
<div class='tagging' macro='tagging'></div>
<div class='tagged' macro='tags'></div>
<div class='viewer' macro='view text wikified'></div>
<div class='tagClear'></div>
<!--}}}-->
When you send a mailshot, we include a link to a web version of it (using the {{{[[$mailshot.webversion_url]]}}} [[template tags|TemplateGuide]]), typically placed at the very top of your message as a simple text link, that will open in a recipient's web browser instead of their email program.
!!Why provide a web version link?
Web version links are commonly used by recipients for these main reasons:
#The message they received has been corrupted/rewritten/filtered in some way, rendering it unreadable or degraded in some way.
#They have images turned off and don't want to turn them on to view images (usually for security or privacy reasons)
#Their email program doesn't support HTML, e.g. it's on an older mobile phone, or a text-only email program such as Eudora or Mutt.
All of these have one thing in common – when the recipient looks at your message, they are already seeing a degraded version in one way or another; the web version link is thus provided as a last-ditch attempt to help those recipients to see what you intended.
The first of these is common if you're sending to business customers with outsourced email systems and web-mail clients such as gmail, both of which are often heavy-handed with their mail filtering, sometimes to the point of completely destroying messages. Ideally messages would not get corrupted, but they do (in ways we have no control over), so we need to be defensive and put additional effort into making sure that these links work when others might not. The biggest factor in URL breakage is length. Many breakages are down to ~URLs being too long – and in a environment of multiply-nested ad tracker links with large, messy parameter lists (I'm looking at you, tradedoubler!), these can often get to several hundred characters long. So we keep web version ~URLs as short as possible. The biggest thing we typically add to a URL is a user identifier, and by removing that we save up to 40 characters – and when a length limit may be less than 72 characters, that's enough to make the difference.
Many users fall into the second group because that's the default behaviour of most email clients, whether desktop, web or mobile. Users that are already sufficiently paranoid about security and privacy will also be fully aware of identifiers in ~URLs, so will not click a link with obvious embedded data in anyway, even if it would provide a better looking result.
The third reason probably has a lot of overlap with the second – many privacy advocates are also keen users of text-only mail programs – but many such users actively prefer text-only programs as they are significantly smaller and faster than the likes of Outlook. It's also another reason to make sure you produce a properly formatted plain-text version of your template.
There are other factors too: by serving a static, generic web version of your mailshot we can dramatically improve performance, probably by a factor of over 100. Our re-usable templates are a big feature that's unique to us – but what happens if you change your template after you've sent it (perhaps when preparing for your next send)? By keeping a 'frozen' copy of the mailshot, we avoid that problem, and it also acts as a kind of audit on exactly what was sent – if someone makes a mistake there's no covering it up!
We'd estimate that typically less than 1% of recipients are affected by these factors, so we're already talking about a very small proportion – a recent analysis showed around 1 in 500 users who opened the messages used the web version, which only accounted for about 1 in 20000 of the overall mailing. Of course you want to catch them all, but it's important to keep some perspective – do you consider it more important that someone sees your message, or that you know that they have done so, when trying to keep that connection may mean they don't see it at all? The time and effort required to chase down these last few people is much better spent on the probably >75% that don't log any activity at all!
For all of these reasons, in common with most other email marketing services, we don't do personalisation of web versions by default in an effort to keep the links working, avoid exposing personal data, and avoid turning away otherwise perfectly good customers.
!!Personalised web versions
Despite the above, we do provide the ability to override this behaviour in your own templates. Normally we use the equivalent of the generic {{{[[$mailshot.webversion_link]]}}} template tag; there is a personalised alternative in {{{[[$message.webversion_url]]}}} which will provide a link or ~URL to a fully personalised web version, however you should only use this with the full understanding that:
* You may potentially expose personal data, at your own risk
* It's much less likely to work
* Performance will be reduced
* Privacy-aware recipients are less likely to use it
* You can be defeating the entire point of having a web version at all
In short ''we strongly recommend you do not do this''.
<<tiddler SiteTitle>> - <<tiddler SiteSubtitle>>
Whether you're using a hosted site from [[wordpress.com|https://wordpress.com/]] or a self-hosted instance from [[wordpress.org|https://wordpress.org/]], it's likely you want to get people to sign up to your Smartmessages mailing lists from your site. There are several ways of doing this, varying in complexity and flexibility. Your subscribers are likely to end up on pages we serve at some point (like subscribe and verification pages), so it will help if you [[set up your branding|Branding]] to make these pages look like your own.
!!Signup page links
The most straightforward way to add subscriptions to a single list is via a simple link to one of your signup pages, and you can use that anywhere that you can create a link in ~WordPress, such as in a sidebar element or within a blog post. You can find all your mailing lists on [[your Contacts page|https://www.smartmessages.net/contacts.php]], and there's a link to each one in the "Signup links" column – if you right click on the link and select "copy link", that's the URL you need. The URL will look like {{{https://www.smartmessages.net/subscribe/<list id>}}}, where {{{<list id>}}} is a unique identifier for the specific list.
This URL is not the end of the story – it's possible to add various parameters to the URL to let you [[control how the signup page behaves|Subscribing]].
!!Landing page link
Every Smartmessages account has a standard landing page which provides simple check-box subscriptions to all your lists (that are marked as visible) at once, and also to capture data from your subscribers. You'll find the link to the landing page on [[your Contacts page|https://www.smartmessages.net/contacts.php]]. Like the individual list signup pages, all this needs is a simple link from your ~WordPress site.
!!HTML forms
On the actions tab for each of your mailing lists you'll find an HTML form ([[more details|Subscribing]]) – you can copy and paste this form into anywhere that permits raw HTML in ~WordPress.
!!Form builder plugins
There isn't an official Smartmessages plugin because there is no need – there are [[many excellent, well-supported WordPress form-builder plugins|https://wordpress.org/plugins/search/form+builder/]] available that will work with Smartmessages – we're not interested in reinventing the wheel just so we can put our logo on one! Obviously how you use them will vary, but they will all be able to do these basic things:
* Set the "action" parameter to {{{https://www.smartmessages.net/subscribe.php}}}
* Add a hidden field named {{{command}}} containing the value {{{subscribe}}}
* Add a hidden field named {{{mlid}}} containing the unique ID for the list you want users to subscribe to (see [[how to find that|Subscribing]])
* Add an email (if available) or text type field called {{{emailaddress}}}
There are [[many other options available|Subscribing]] to give you more flexibility and control over your form, but these are the ones that are strictly necessary.
There’s no escaping it: building reliable responsive email templates is hard. While Smartmesssages provides a great array of tools to help you build your templates, we can’t claim to have everything! Email client applications like Apple Mail, Outlook and Gmail vary wildly in how they present HTML messages, and it becomes even harder when you take different devices into account. Zurb’s Foundation for Emails 2.0 changes all that.
[[Design agency Zurb|http://zurb.com/]] has a long history of maintaining the [[Foundation framework|http://foundation.zurb.com/]], a competitor to the popular [[Bootstrap framework|http://getbootstrap.com/]] (which Smartmessages uses). These are both frameworks used for building responsive (a term used to describe HTML layouts that adapt to multiple screen sizes automatically) web sites, but what if you could apply the same kind of approach to email templates? That’s exactly what Zurb did when they introduced Ink in 2013. In 2016, Ink was overhauled and renamed “[[Foundation for Emails 2.0|http://foundation.zurb.com/emails.html]]“, which I’ll call “~ZF2” to retain typing sanity…
~ZF2 streamlines Ink’s original approach, and uses a combined {{{<div>}}} and {{{<table>}}}-based layout to build templates that adapt or degrade gracefully on an enormous array of screen sizes, devices and services. It can simplify layout creation enormously, and the base styles have been tested extensively on many clients and devices, making for far more reliable rendering and consistent markup.
~ZF2 provides a toolkit of HTML snippets and CSS rules to help you build responsive layouts quickly and easily. Smartmessages provides built-in hosting of ~ZF2’s base style sheet, so your templates remain easy to edit, and we’ve adapted ~ZF2’s example templates with Smartmessages tags (such as for greetings, unsubscribe, privacy links and contact details), which you can use as-is or as the basis for your own layouts. Smartmessages’ integrated CSS inliner means you don’t have to use an external service to inline your styles, making editing and testing a much more straightforward process.
~ZF2 also adds a new feature called “Inky”, a high-level HTML meta-language that simplifies construction of HTML layouts – we don’t have built-in support for that, but you can simply use the Inky (and SASS) build tools supplied with ~ZF2 and paste the results into Smartmessages.
!Using Zurb Foundation for Emails in Smartmessages
When you’re editing a mailshot, just pick one of the “🐙 ~ZF2”-prefixed templates from the template menu or gallery (don’t you just love that little octopus emoji?!), and it will be inserted directly into the WYSIWYG editor, ready for you to customise.
If you’re building your own, you can pull in the ~ZF2 base styles with a link tag in your head tag:
{{{
<link rel="stylesheet" href="/styles/zurbfoundation-2.1.css"/>
}}}
and no, you don’t need to worry about that being a relative URL – it will be imported and [[inlined|CSS Inlining]] for you when you send!
!!Bonus RSS features
Smartmessages makes use of ~ZF2 styles for some RSS features. These make it super-simple to implement multi-column, ~RSS-driven content from right within your templates using a single tag! See our [[RSS]] documentation for details.
!!Documentation and support
Like all good software, [[ZF2 provides documentation|http://foundation.zurb.com/emails/docs/css-guide.html]] to help you get started.
~ZF2 is an open-source project (like [[PHPMailer|https://github.com/PHPMailer/PHPMailer]] that we maintain), so you can (just as we have) submit bug reports, make corrections and provide suggestions and contributions via [[the ZF2 GitHub project|https://github.com/zurb/foundation-emails]].