Jay Jiang

Sending emojis in SMS via Twilio

Blog Post created by Jay Jiang on Nov 7, 2019

Curiously looked into emojis in SMS and wanted to share some learnings here... 

 

There are a few different options...

 

1. Hard code your SMS templates and have 1 webhook per SMS template

Marketo has a problem of saving emojis in tokens (either my.tokens text/rich text or lead.tokens). It doesn't let you store emojis and straight away removes any emojis in the token.

 

 

 

However, emojis in the webhook payload section do get saved and will get sent as emojis (tested using Twilio)

 

 

While functional, this is not scalable.

 

2. Use the url encoded version of the emoji - BUT there are strict requirements you'd need to adhere to for it to work

Check out charbase.com (https://charbase.com/1f602-unicode-face-with-tears-of-joy) for URL encoded versions of emojis. Truncate the "q=", you only need the stuff with %.

Your Marketo webhook needs to have Request Token Encoding: = None. But this can cause issues because you may have nicely formatted numbers like "+61432123456" in your database. With no encoding, + signs are actually the same as a space when sent over http and so the phone number becomes "To= 61432123456" - which Twilio doesn't recognise as a legit phone number.

If you're normalising your phone numbers and storing country codes separately to the phone number field, you can hard code the url encoded version of the + sign in your payload e.g. "To=%2B{{lead.Phone Country Code}}{{lead.Mobile Phone Number}}". But I suspect the number of people with such a squeaky clean database wouldn't be that many!

 

3. Use a handler service to forward your payload to Twilio

Using the same emoji encoding as above...

If you want scalability and robustness, use a handler to rewrite your payload and forward it to Twilio. This also means you'll need access to a server to host the handler (be mindful servers have varying levels of performance, so if you're sending tens of thousands of SMS in short bursts, make sure your server can handle the requests)

 

I've written this in php but you can work in any server side language you want:

<?php
/* Add some auth/security here */
$accId = '<accId>'; // your twilio account Id
$token = '<token>'; // your twilio token
$url = "https://$accId:$token@api.twilio.com//2010-04-01/Accounts/$accId/Messages.json";
$payload = array(
'From' => urlencode($_POST["From"]),
'To' => urlencode($_POST["To"]),
'Body' => urlencode(urldecode($_POST["Body"]))
);
foreach ($payload as $key => $value) {
$parts[] = $key . '=' . $value;
}
$data = implode('&', $parts);
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$result = curl_exec($ch);
curl_close($ch);
echo $result;
?>
With this option, make sure you're using Request Token Encoding: = Form/Url in your webhook settings. Your Marketo webhook endpoint will now be the path to the file you're hosting on your server.
The handler service essentially on-forwards the payload to Twilio while being more lenient on phone number formatting. If your phone numbers are very messy in the database, this option also allows you to normalise phone numbers before forwarding it in the payload to Twilio.
3.1 *Fun* Use tokens in your tokens
Related to a handler service, if you have a few regular emojis you use, another option is to apply a find-and-replace way of writing your tokens, essentially having "emoji tokens" in your my.tokens. Of course, this means you'll have to maintain the array of tokens if you want to use more, but writing tokens would be more efficient without the need to look up charbase.com all the time.
P.S. Don't use double curly brackets for your proprietary tokens as they are reserved for Marketo system
The amended code:
<?php
$emojis = [ // these are emojis that php version 7+ understands
'smile'=>"\u{1F603}",
'grin'=>"\u{1F601}",
'laughntears'=>"\u{1F602}"
];

$string = $_POST["Body"];
$do = true;
while($do){ // find and replace loop
if(stristr($string,"{emoji.")){
$start = stripos($string,"{emoji.");
$end = stripos($string,"}",$start) + 1;
$find = substr($string,$start,$end - $start);
$emoji = isset($emojis[rtrim(explode(".",$find)[1],"}")]) ? $emojis[rtrim(explode(".",$find)[1],"}")] : rtrim(explode(".",$find)[1],"}");
$string = str_replace($find,$emoji,$string);
} else {
$do = false;
}
}

$accId = '<accId>'; // your twilio account Id
$token = '<token>'; // your twilio token
$url = "https://$accId:$token@api.twilio.com//2010-04-01/Accounts/$accId/Messages.json";
$payload = array(
'From' => urlencode($_POST["From"]),
'To' => urlencode($_POST["To"]),
'Body' => urlencode($string)
);

foreach ($payload as $key => $value) {
$parts[] = $key . '=' . $value;
}
$data = implode('&', $parts);

$ch = curl_init($url);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$result = curl_exec($ch);
curl_close($ch);

echo $result;
?>

Outcomes