Use SendGrid to send emails with Voiceflow

Hello everyone, in this tutorial we will discover together how to use the SendGrid API with the Voiceflow Integration block to send emails to users of your Alexa skill.

For those who do not know SendGrid, this service allows you to automate the sending of emails (among other things) via an online tool or an API.

So it is the API part that will interest us in this tutorial, and you will see how, with a simple API call, you will be able to send personalized emails to your users.

1) OBTAIN USER INFORMATION
Configure our project to retrieve the user’s name and email

Let’s start by creating a new blank project in Voiceflow. For this tutorial, I’ll call mine SendGrid Demo.

As we will customize our email we will have to retrieve information such as the user’s email or name for example. We will also generate a personalized message. All this information will have to be stored in variables, so let’s start by creating three variables in the Variables section of Voiceflow.

For this tutorial, the variables used will be:

  • name
  • email
  • message

40%20AM

Now, we will add the User Info block and the Permission block to our project. Let’s also add a Speak block to explain to the user why we will need some information about him or her and how to authorize this.

Your project should now look like this.

In the User Info block, add permission for the User Email and map the User Email to the {email} variable we’ve just created.

Do the same with User Name and map it to the {name} variable.

Finally, in our speak block we will explain why and how the user should give us access to his name and email.

In order to be able to send you information we need to have access to your name and email. 
<break time="1s"/>To authorize this, please click on the authorization request card that has just
been displayed in your Alexa application on your mobile phone or on alexa.amazon.com 
<break time="0.5s"/>
Once the necessary authorizations have been granted, please restart our skill by saying: 
<break time="0.5s"/>Alexa, open SendGrid Demo!  

2) SENDGRID TEMPLATE
Configure SendGrid, create your API key and make a template

As explained at the beginning of this tutorial, we will use the SendGrid service to send our email to our users.
Start by creating a (free) account on https://signup.sendgrid.com
(or login if you already have an account with them:)

Their free Email API Plan allows you to send 40,000 emails for 30 days and then 100/day after that period.

Once your account is created and/or you are connected to SendGrid, go to Settings -> API keys
or use this url: https://app.sendgrid.com/settings/api_keys

Click on

image

and on the following screen, name your API key and give it Full Access.

Then hit

image

As explained on the next screen, copy the key and save it somewhere safe.
We’re going to need this key for the last step of our tutorial.

Now we will create our template. This template will be used for each API call we make from Voiceflow.
To do this, click on Templates -> Transactional or use this url: https://sendgrid.com/dynamic_templates

Now click on image

give your new template a name

and hit image

Let’s now create a new version for this template. Click on image

You can create your template using the Design Editor or the Code Editor but for this tutorial, we will use the Code Editor. Select this choice and click on image

In the editor, remove the - , and copy the following code

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html data-editor-version="2" class="sg-campaigns" xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1" /><!--[if !mso]><!-->
    <meta http-equiv="X-UA-Compatible" content="IE=Edge" /><!--<![endif]-->
    <!--[if (gte mso 9)|(IE)]>
    <xml>
    <o:OfficeDocumentSettings>
    <o:AllowPNG/>
    <o:PixelsPerInch>96</o:PixelsPerInch>
    </o:OfficeDocumentSettings>
    </xml>
    <![endif]-->
    <!--[if (gte mso 9)|(IE)]>
    <style type="text/css">
      body {width: 600px;margin: 0 auto;}
      table {border-collapse: collapse;}
      table, td {mso-table-lspace: 0pt;mso-table-rspace: 0pt;}
      img {-ms-interpolation-mode: bicubic;}
    </style>
    <![endif]-->

    <style type="text/css">
      body, p, div {
        font-family: verdana,geneva,sans-serif;
        font-size: 16px;
      }
      body {
        color: #8d9db9;
      }
      body a {
        color: #fe5d61;
        text-decoration: none;
      }
      p { margin: 0; padding: 0; }
      table.wrapper {
        width:100% !important;
        table-layout: fixed;
        -webkit-font-smoothing: antialiased;
        -webkit-text-size-adjust: 100%;
        -moz-text-size-adjust: 100%;
        -ms-text-size-adjust: 100%;
      }
      img.max-width {
        max-width: 100% !important;
      }
      .column.of-2 {
        width: 50%;
      }
      .column.of-3 {
        width: 33.333%;
      }
      .column.of-4 {
        width: 25%;
      }
      @media screen and (max-width:480px) {
        .preheader .rightColumnContent,
        .footer .rightColumnContent {
            text-align: left !important;
        }
        .preheader .rightColumnContent div,
        .preheader .rightColumnContent span,
        .footer .rightColumnContent div,
        .footer .rightColumnContent span {
          text-align: left !important;
        }
        .preheader .rightColumnContent,
        .preheader .leftColumnContent {
          font-size: 80% !important;
          padding: 5px 0;
        }
        table.wrapper-mobile {
          width: 100% !important;
          table-layout: fixed;
        }
        img.max-width {
          height: auto !important;
          max-width: 480px !important;
        }
        a.bulletproof-button {
          display: block !important;
          width: auto !important;
          font-size: 80%;
          padding-left: 0 !important;
          padding-right: 0 !important;
        }
        .columns {
          width: 100% !important;
        }
        .column {
          display: block !important;
          width: 100% !important;
          padding-left: 0 !important;
          padding-right: 0 !important;
          margin-left: 0 !important;
          margin-right: 0 !important;
        }
      }
    </style>
    <!--user entered Head Start-->
    
     <!--End Head user entered-->
  </head>
  <body>
    <center class="wrapper" data-link-color="#fe5d61" data-body-style="font-size: 16px; font-family: verdana,geneva,sans-serif; color: #8d9db9; background-color: #f2f4fb;">
      <div class="webkit">
        <table cellpadding="0" cellspacing="0" border="0" width="100%" class="wrapper" bgcolor="#f2f4fb">
          <tr>
            <td valign="top" bgcolor="#f2f4fb" width="100%">
              <table width="100%" role="content-container" class="outer" align="center" cellpadding="0" cellspacing="0" border="0">
                <tr>
                  <td width="100%">
                    <table width="100%" cellpadding="0" cellspacing="0" border="0">
                      <tr>
                        <td>
                          <!--[if mso]>
                          <center>
                          <table><tr><td width="600">
                          <![endif]-->
                          <table width="100%" cellpadding="0" cellspacing="0" border="0" style="width: 100%; max-width:600px;" align="center">
                            <tr>
                              <td role="modules-container" style="padding: 0px 0px 0px 0px; color: #8d9db9; text-align: left;" bgcolor="#f2f4fb" width="100%" align="left">
                                
    <table class="module preheader preheader-hide" role="module" data-type="preheader" border="0" cellpadding="0" cellspacing="0" width="100%"
           style="display: none !important; mso-hide: all; visibility: hidden; opacity: 0; color: transparent; height: 0; width: 0;">
      <tr>
        <td role="module-content">
          <p>You've found the secret!</p>
        </td>
      </tr>
    </table>
  
    <table class="wrapper" role="module" data-type="image" border="0" cellpadding="0" cellspacing="0" width="100%" style="table-layout: fixed;">
      <tr>
        <td style="font-size:6px;line-height:10px;padding:30px 0px 30px 0px;" valign="top" align="left">
          <img class="max-width" border="0" style="display:block;color:#000000;text-decoration:none;font-family:Helvetica, arial, sans-serif;font-size:16px;max-width:40% !important;width:40%;height:auto !important;" src="https://s3.amazonaws.com/static.sendgrid.com/8580bc02-00ef-48a1-bccd-554777047aed.png" alt="Off Grid Adventures" width="240">
        </td>
      </tr>
    </table>
  
    <table class="wrapper" role="module" data-type="image" border="0" cellpadding="0" cellspacing="0" width="100%" style="table-layout: fixed;">
      <tr>
        <td style="font-size:6px;line-height:10px;padding:0px 0px 0px 0px;" valign="top" align="center">
          <img class="max-width" border="0" style="display:block;color:#000000;text-decoration:none;font-family:Helvetica, arial, sans-serif;font-size:16px;max-width:100% !important;width:100%;height:auto !important;" src="https://s3.amazonaws.com/static.sendgrid.com/8436c86a-e411-4fcb-bb1c-c8a376933ae5.png" alt="" width="600">
        </td>
      </tr>
    </table>
  
    <table class="module" role="module" data-type="text" border="0" cellpadding="0" cellspacing="0" width="100%" style="table-layout: fixed;">
      <tr>
        <td style="background-color:#FE5D61;padding:50px 0px 030px 0px;line-height:22px;text-align:inherit;"
            height="100%"
            valign="top"
            bgcolor="#FE5D61">
            <div style="text-align: center;"><span style="font-size:24px;"><span style="font-family:courier,monospace;"><span style="color:#FFFFFF;">Welcome to the family!</span></span></span></div>
        </td>
      </tr>
    </table>
  
    <table class="module" role="module" data-type="text" border="0" cellpadding="0" cellspacing="0" width="100%" style="table-layout: fixed;">
      <tr>
        <td style="background-color:#fe5d61;padding:30px 50px 30px 50px;line-height:22px;text-align:inherit;"
            height="100%"
            valign="top"
            bgcolor="#fe5d61">
            <div style="text-align: center;"><span style="font-family:courier,monospace;"><span style="color:#FFFFFF;">Hello {{name}}, you've found a community of travelers that are just like you.</span></span></div>

<div style="text-align: center;">&nbsp;</div>

<div style="text-align: center;"><span style="font-family:courier,monospace;"><span style="color:#FFFFFF;">{{message}}</span></span></div>

<div style="text-align: center;">&nbsp;</div>

<div style="text-align: center;"><span style="font-family:courier,monospace;"><span style="color:#FFFFFF;">Ready for your next authentic travel experience?</span></span></div>
        </td>
      </tr>
    </table>
  <table border="0" cellPadding="0" cellSpacing="0" class="module" data-role="module-button" data-type="button" role="module" style="table-layout:fixed" width="100%"><tbody><tr><td align="center" bgcolor="#fe5d61" class="outer-td" style="padding:10px 10px 60px 10px;background-color:#fe5d61"><table border="0" cellPadding="0" cellSpacing="0" class="button-css__deep-table___2OZyb wrapper-mobile" style="text-align:center"><tbody><tr><td align="center" bgcolor="#ffffff" class="inner-td" style="border-radius:6px;font-size:16px;text-align:center;background-color:inherit"><a style="background-color:#ffffff;border:1px solid #333333;border-color:#ffffff;border-radius:3px;border-width:1px;color:#fe5d61;display:inline-block;font-family:courier new,courier,monospace;font-size:16px;font-weight:700;letter-spacing:1px;line-height:40px;padding:012px 20px 12px 20px;text-align:center;text-decoration:none" href="" target="_blank">Browse Gallery</a></td></tr></tbody></table></td></tr></tbody></table>
    <table class="wrapper" role="module" data-type="image" border="0" cellpadding="0" cellspacing="0" width="100%" style="table-layout: fixed;">
      <tr>
        <td style="font-size:6px;line-height:10px;padding:0px 0px 0px 0px;" valign="top" align="center">
          <img class="max-width" border="0" style="display:block;color:#000000;text-decoration:none;font-family:Helvetica, arial, sans-serif;font-size:16px;max-width:100% !important;width:100%;height:auto !important;" src="https://s3.amazonaws.com/static.sendgrid.com/d3738cc0-44ed-4d10-880f-b1f71b937871.png" alt="" width="600">
        </td>
      </tr>
    </table>
  
    <table class="module"
           role="module"
           data-type="spacer"
           border="0"
           cellpadding="0"
           cellspacing="0"
           width="100%"
           style="table-layout: fixed;">
      <tr>
        <td style="padding:0px 0px 30px 0px;"
            role="module-content"
            bgcolor="">
        </td>
      </tr>
    </table>
  
    <table class="module"
           role="module"
           data-type="divider"
           border="0"
           cellpadding="0"
           cellspacing="0"
           width="100%"
           style="table-layout: fixed;">
      <tr>
        <td style="padding:0px 0px 0px 0px;"
            role="module-content"
            height="100%"
            valign="top"
            bgcolor="">
          <table border="0"
                 cellpadding="0"
                 cellspacing="0"
                 align="center"
                 width="100%"
                 height="3px"
                 style="line-height:3px; font-size:3px;">
            <tr>
              <td
                style="padding: 0px 0px 3px 0px;"
                bgcolor="#ffffff"></td>
            </tr>
          </table>
        </td>
      </tr>
    </table>
  
    <table class="module"
           role="module"
           data-type="spacer"
           border="0"
           cellpadding="0"
           cellspacing="0"
           width="100%"
           style="table-layout: fixed;">
      <tr>
        <td style="padding:0px 0px 30px 0px;"
            role="module-content"
            bgcolor="">
        </td>
      </tr>
    </table>
  
    <table class="module" role="module" data-type="social" align="center" border="0" cellpadding="0" cellspacing="0" width="100%" style="table-layout: fixed;">
      <tbody>
        <tr>
          <td valign="top" style="padding:0px 0px 0px 0px;font-size:6px;line-height:10px;">
            <table align="center">
              <tbody>
                <tr>
                  <td style="padding: 0px 5px;">
        <a role="social-icon-link"  href="https://www.facebook.com/" target="_blank" alt="Facebook"
          data-nolink="false"
          title="Facebook "
          style="-webkit-border-radius:2px;-moz-border-radius:2px;border-radius:2px;display:inline-block;background-color:rgb(254, 93, 97);">
          <img role="social-icon" alt="Facebook" title="Facebook "
            height="30"
            width="30"
            style="height: 30px, width: 30px"
            src="https://marketing-image-production.s3.amazonaws.com/social/white/facebook.png" />
        </a>
      </td>
                  <td style="padding: 0px 5px;">
        <a role="social-icon-link"  href="https://twitter.com/" target="_blank" alt="Twitter"
          data-nolink="false"
          title="Twitter "
          style="-webkit-border-radius:2px;-moz-border-radius:2px;border-radius:2px;display:inline-block;background-color:rgb(254, 93, 97);">
          <img role="social-icon" alt="Twitter" title="Twitter "
            height="30"
            width="30"
            style="height: 30px, width: 30px"
            src="https://marketing-image-production.s3.amazonaws.com/social/white/twitter.png" />
        </a>
      </td>
                  <td style="padding: 0px 5px;">
        <a role="social-icon-link"  href="https://www.instagram.com/" target="_blank" alt="Instagram"
          data-nolink="false"
          title="Instagram "
          style="-webkit-border-radius:2px;-moz-border-radius:2px;border-radius:2px;display:inline-block;background-color:rgb(254, 93, 97);">
          <img role="social-icon" alt="Instagram" title="Instagram "
            height="30"
            width="30"
            style="height: 30px, width: 30px"
            src="https://marketing-image-production.s3.amazonaws.com/social/white/instagram.png" />
        </a>
      </td>
                  
                  <td style="padding: 0px 5px;">
        <a role="social-icon-link"  href="https://www.pinterest.com/" target="_blank" alt="Pinterest"
          data-nolink="false"
          title="Pinterest "
          style="-webkit-border-radius:2px;-moz-border-radius:2px;border-radius:2px;display:inline-block;background-color:rgb(254, 93, 97);">
          <img role="social-icon" alt="Pinterest" title="Pinterest "
            height="30"
            width="30"
            style="height: 30px, width: 30px"
            src="https://marketing-image-production.s3.amazonaws.com/social/white/pinterest.png" />
        </a>
      </td>
                  
                </tr>
              </tbody>
            </table>
          </td>
        </tr>
      </tbody>
    </table>
  <div data-role="module-unsubscribe" class="module unsubscribe-css__unsubscribe___2CDlR" role="module" data-type="unsubscribe" style="color:#8d9db9;font-size:12px;line-height:20px;padding:16px 16px 16px 16px;text-align:center"><div class="Unsubscribe--addressLine"><p class="Unsubscribe--senderName" style="font-family:Arial,Helvetica, sans-serif;font-size:12px;line-height:20px">[Sender_Name]</p><p style="font-family:Arial,Helvetica, sans-serif;font-size:12px;line-height:20px"><span class="Unsubscribe--senderAddress">[Sender_Address]</span>, <span class="Unsubscribe--senderCity">[Sender_City]</span>, <span class="Unsubscribe--senderState">[Sender_State]</span> <span class="Unsubscribe--senderZip">[Sender_Zip]</span> </p></div><p style="font-family:Arial,Helvetica, sans-serif;font-size:12px;line-height:20px"><a class="Unsubscribe--unsubscribeLink" href="<%asm_group_unsubscribe_raw_url%>">Unsubscribe</a> - <a class="Unsubscribe--unsubscribePreferences" href="<%asm_preferences_raw_url%>">Unsubscribe Preferences</a></p></div>
                              </td>
                            </tr>
                          </table>
                          <!--[if mso]>
                          </td></tr></table>
                          </center>
                          <![endif]-->
                        </td>
                      </tr>
                    </table>
                  </td>
                </tr>
              </table>
            </td>
          </tr>
        </table>
      </div>
    </center>
  </body>
</html>

And paste it in the SendGrid code editor.

Your screen should now look like this

If you move to line 167, you will see how you can use variables in SendGrid. Here for example, in the text Hello {{name}}, {{name}} will be replaced by the value of the variable.

To test that, click on image
and add the following code:

{
  "subject":"OFF GRID ADVENTURES // ALEXA SKILL",
  "name":"Nicolas",
  "message":"We don't want to be stuck in tourist traps that isolate us from vibrant, local experiences. We want to discover the hidden gems and less-traveled roads of our next destination."
}

The preview is now updated with the test data

To finish with this template, open the Settings panel on the left

Give your template a name and add the {{subject}} variable in the Email Subject field

Hit image and go back to your dashboard image

To finish, as for the API key, copy the ID of your template and save it for the next step.

3) VOICEFLOW INTEGRATION BLOCK
Use the Integration block to send your email with the SendGrid API

For this last step, we will use the Integration block. Add this block to your project and link the User Info block to it.

Click on the Integration block, select Custom API and Make a POST Request

In the With setting section, add:

https://api.sendgrid.com/v3/mail/send

in the URL field.

This is the POST request that allows you to send an email via the SendGrid API, if you want to have more information about the SendGrid API, you can browse here: https://sendgrid.com/docs/api-reference/

To authenticate with the SendGrid API we will have to send it the API key we created earlier. As stated in the SendGrid API documentation, we must use the Authorization header. So let’s add this header to our Integration block and we will also add the Content-Type header at the same time.

For Authorization, we will enter Bearer followed by a space and your API key.

Bearer SG.BdXF-MveTD-nGj.....

For Content-Type, just type

application/json

Your settings should now look like this

Finally, in the Body -> Raw Input part, copy and paste the following code:

{  
       "from":{"email":"youremail@domain.com"},
       "personalizations":[  
          {  
             "to":[{"email":"{email}","name":"{name}"}],
             "dynamic_template_data":{
               "name":"{name}",
               "message":"{message}",
               "subject":"OFF GRID ADVENTURES // ALEXA SKILL"
             }
          }
       ],
       "template_id":"templateid"
}

Replace youremail@domain.com with the email associated with your SendGrid account and also replace templateid with the ID of the template you created previously.

Time to test our Integration block, hit

and fill the next screen with testing data

Click on image

If everything is well configured you should have this message and a new email in your inbox.

To summarize, here we send the template we just created to the email present in the variable {email} with the name {name}.
We still have to add our message to the {message} variable, so let’s do it now.

Let’s add a Set block and put the text

We don't want to be stuck in tourist traps that isolate us from vibrant, local experiences. We want to discover the hidden gems and less-traveled roads of our next destination.

in the {message} variable.

To avoid any problems when sending the message to the API we need to clean up our message. To do this, we add a Code block with the following code:

message = message.replace(/\\/g, "");

Finally, add two Speak blocks, one in case of success and another in case of error to warn the user.

For your information, to be able to fully test this skill (and in particular the User Info / Permission part), you must upload it to Alexa and test it in the Alexa simulator, from your Alexa application or from an Alexa device.

TO CONCLUDE

Congratulations, you can now send personalized emails to your users thanks to Voiceflow and the SendGrid API. You can use more variables to further customize your emails but the basics are there.

Feel free to like, share and comment on this article and see you soon for a next tutorial.

1 Like