Send Transactional Emails With Twilio SendGrid
with Nathaniel Okenwa
As part of Jamstack Conf, Jason is building a swag app with experts from around the community. This 5-part series will go through the whole process of building an e-commerce site with Shopify, Algolia, Sentry, Twilio, and Fauna.
Resources & Links
Captions provided by White Coat Captioning (https://whitecoatcaptioning.com/). Communication Access Realtime Translation (CART) is provided in order to facilitate communication accessibility and may not be a totally verbatim record of the proceedings.
JASON: Hello, everyone, and welcome to another episode of Learn With Jason. Today on the show we're bringing back Nathaniel Okenwa. What is up? How you doing, man?
NATHANIEL: I'm doing good, thanks. And yourself?
JASON: I'm doing great. So happy to have you back. Always a pleasure to have you on the show. Especially today because this is by far the most ambitious stream we've ever done. It's a five-parter, and you're coming in for part four.
NATHANIEL: It's like a long relay race, right. I'm hoping I can grab this baton and take it forward to the next person.
JASON: Except instead of a baton, you got to carry me. (Laughter)
NATHANIEL: Even better. Even better, I promise.
JASON: Yeah, so we'll talk about exactly what we're building in a second, but first, for everybody who's not familiar, do you want to give us a little bit of a background on yourself?
NATHANIEL: Hi, my name is Nathaniel Okenwa. I'm a developer working for this awesome company. I'm pointing the wrong direction. Twilio is a company with a couple APIs and tools and different things that developers can use to build communications into their apps, whether it's messaging, video, phone calls. Any form of communication, we probably have an API for that. I heard on the grapevine you're building something that might need some of our tools. So I thought I'd come over and help you.
JASON: Absolutely. And I appreciate you taking time out. I know that this has not been a light period, right. You just had Signal Conf happen, right?
NATHANIEL: Yes, we just had Signal wrap up last week. So it was last week Wednesday and Thursday. It's our big event where we get to make all of our product announcements. We get to show off really cool things. We had Signal TV, which is where we just hang out and have really -- just fun, and we get to see really weird and fun projects. My favorite one is someone built a phone number you could text with ingredients, and it comes back with a recipe. However, you can text it with random ingredients, and it comes back with a random recipe because it uses GPT3 to format your ingredients in a recipe-style piece of text. So if you throw concrete at it, it'll be like, mix the concrete, stir in the raisins, and put it in the oven at 300 degrees Celsius. It's hilarious. But there are also really serious things. People who maybe do email marketing, there are ways to make sure you're hitting the right people at the right times. One thing that I've been really, really interested and excited because it just got announced, it's going into private beta, is Twilio Live, which helps you manipulate different participants in a video call room and stream that out. You can make all sorts of designs. We're having a conversation about this, and you were saying it was tasty.
JASON: Yeah, I'm really, really excited for this one. The thing that's really exciting about that to me is one of the big challenges of doing web-based streaming is that a lot of times the video kind of happens externally from the rest of the stream. That means that a lot of things can be playful and involved. That part is great. But then the videos are kind of held apart. So I want to do silly stuff like let people choose what my hat says and use facial recognition to, like, put something on my hat, right. That sounds really fun to me. But I can't do that right now because this video is not part of the website. It's separate from it. So this offering has me really excited for what's possible, and I can't wait to dig into it. I think it's going to be an absolute blast. Yeah, we're seeing some SendGrid love. What's up, dominukkelvin?
NATHANIEL: Hi, folks. Welcome.
JASON: I'm super excited for what we're going to do today. You were talking about email earlier. One of the things I think is a really common challenge whenever you're building something sufficiently ambitious, is you're probably going to find yourself in a situation where you need to send somebody updates. They're going to buy something. They're going to perform an action. They're going to need a reminder. Something is going to happen in your app that makes sense to send them an email. And not like marketing email where you would, you know, you're sending out a newsletter. More like transactional email. You have done something in the app or need to do something in the app, therefore this email needs to reach you that lets you know, hey, something is going to happen. Hey, you're about to reach your billing threshold. Or hey, you just got an order. You need to fulfill it.
NATHANIEL: Yeah, it's funny, actually. I found out that email is still the most popular channel that people want to be contacted on. But lots of really, really important things happen in email.
JASON: Yeah, I think my whole life at this point is dependent on email and text messages. Like, I don't answer my phone. And yeah, like that's --
NATHANIEL: How many unread emails are you on? This is exposing too much. I'll stop.
JASON: I will say I'm under triple digits. So I'm doing okay.
NATHANIEL: That's good, you know. I reached inbox zero today. I'm very proud of myself.
JASON: Oh, geez. Hold on. You know what I noticed? You don't have your celebratory donut today. You already had it after you hit inbox zero?
NATHANIEL: Oh, you know what, I completely forgot about the donut. Oh, no. My identity -- folks call me the donut king on my stream because every time I build something and make it work, I reward myself with a donut. I just realized I didn't bring one. Don't worry. Right after the stream, I'm going to head over and get some donuts. I'll tweet about it.
JASON: We'll look for the tweet. All right. So what we want to do today, we've been building this app. So let me switch over to the pair programming view here so that we can take a look at it. What we've been working on is this swag app for Jamstack Conf. What we've done thus far is over here. So we have our swag here. We've got the slap bracelet, which you can claim for free. We had Brian Robinson help us do this. If you go to this website -- and I'll drop this in for y'all to try it. If you registered for Jamstack Conf, you can put in the email you used to register for Jamstack Conf, and you can get one of these for free. If you put in Jason@lengstorf, it will give you your code, which currently logs in the console. So this is a very developer-friendly -- wait, did I break this? Crap, I probably broke this, didn't I? No. Okay, we can do it. Do the thing.
NATHANIEL: I am literally going through this to try and get my slap bracelet.
JASON: I really hope I didn't break this. Something is happening that I don't know what it is. Oh, it's not digging this thing. Or not submitting this thing? Do the thing. Hmmm, okay. Curious. Curious that I can't get that to do what I want. But yeah, so this should work. Clearly is not doing that right now. But yeah, anyway, you can also hit the function that we're hitting, and you can find that in the code here. It is a code called -- it's a serverless function called claim swag. Which is somewhere in here. So you can just post your email address as email to claim swag. That'll give you back a code and register you to get a free thingy. But we also have this wonderful swag pack that I have a discount code for. So if you want 25% off of this thing, if I can find the discount code, which is in my inbox on Slack. Oh, my goodness.
NATHANIEL: There's really cool stickers inside that swag pack. There's some stickers that are really catching my eye. The Netlify sticker. Nice, the wonderful character, that little owl. With a backpack, looking good. What a developer, eh?
JASON: Can we just zoom in? Look at this. This is some good stuff. So you can get all of this. It is listed at 40 bucks, but we have a 25% off discount. It's two T-shirts. This is a bath bomb. You get a pop socket, a bunch of stickers. So this is all from sponsors, Netlify, Algolia, Contentful, Sentry, Commerce Layer. It helps us keep the lights on with the conference. It's very expensive to run a conference. This makes it all possible through the generous support of sponsors who may most of the bills and then things like this that help us give away swag at less than cost. That's what I'll say. (Laughter) But so anyway, that is kind of what we've been working on. We already have this integrated with Shopify. This is data pulled from Shopify. If you go to build one of these, we can claim the bracelet and here it is. If I go to check out, it's going to take me over to the Shopify checkout. Then we get -- like here we go. Our discount code is done. I can complete that order and get my slap bracelet. We've got Algolia set up with this command bar. We've got -- we used the Shopify cart API to build this actual cart so that we can add and remove things from our cart. It's really powerful, really nice. I screwed up some Z index, which is why that Algolia thing is over the top of it. But this is giving us the ability to very quickly build out these swag packs. This is powerful stuff. But I currently don't have a way to know when someone has claimed anything. Because the notification from Shopify goes to somebody else on my team. The sale notification goes to the person who got the swag, but I don't know if anybody is using this app. So what I was hoping we could do today and what you could help me with is I want to build a transactional email that will let me know whenever somebody has ordered something on the site. For everybody who's watching, what we could do with this is we could, you know, use this to -- if somebody needed to perform an action, if we wanted to let somebody know that, hey, your cart is here, but you haven't checked out yet. You could do a follow-up using transactional email. So this is just one application of how it could work.
NATHANIEL: I mean, the actual transactional emails coming from Shopify are powered by Twilio.
JASON: Oh, are they really?
NATHANIEL: You can now like take that code and actually write for some of your own custom events as well. But sorry, go on.
JASON: I had no idea that SendGrid was behind Shopify. I love finding out that all of the web is kind of powered by the same services.
JASON: And it's cool. It's also just cool to know that, like, you're using something that's trusted by a company that sends as much email as Shopify does. Like, so many businesses are built on Shopify. They have to send probably millions, if not billions, of emails.
NATHANIEL: We send like -- especially Black Friday. Black Friday weekend, like -- I don't want to say a hundred billion, but it's definitely in the tens of billions of emails we send over like a 24 or 48-hour window.
JASON: That's unbelievable. So yeah, we're basically instead of trying to do our own version of email, which you can. There are open-source libraries out there that'll let you send email. They're good, but there's a lot that goes into this. So let's start by -- let's take a look at SendGrid. Well, actually, hold on. Before we do that, let's first and foremost, everybody go follow Nathaniel on Twitter.
NATHANIEL: Oh, thank you.
JASON: Also, if you want to find out more about Twilio, you've got all the videos from Signal on here, right?
NATHANIEL: Yeah. Look at those wonderful people.
JASON: Look at these folks. This is great. So you've got lots of stuff going on here. We've got Twilio itself, if you want to look at all of the things that are happening.
NATHANIEL: That design of the website must have just gone out. I have literally not seen that update. That looks good.
JASON: This looks great. I love this. Oh, good little animations. Yeah, this is good. Congrats to your team on an excellent redesign. That looks awesome.
NATHANIEL: Yeah, this is cool.
JASON: Then we're specifically using Twilio SendGrid today. So this is part of what we're digging into here. And the thing that's nice about SendGrid is there are a huge number of concerns when you're sending email. One of the biggest challenges is how do I not end up in the spam folder? If your email doesn't come in with -- if it looks like it's spoofed, which is what a lot of the open-source libraries end up looking like, unfortunately, because they don't have all this weight of, hey, we're a trustworthy delivery service, you can look like you're spoofed. Then you go into spam. Or if you don't send the right headers, if you don't get these different domain settings right, like all these things can happen that basically make you look like spam, and therefore, your emails never make it to the people you're trying to send them to. So can you talk a little bit about, like, what all is happening with SendGrid to make sure that this stuff actually works?
NATHANIEL: Oh, it's a couple of things. Some of the things you said about all of these headers and all these things that can be easy to forget. But what happens is each of these email service providers, for example like your Hotmails, versus your -- Hotmail, oh, my gosh. I just aged myself. Like your Microsoft emails versus your Google emails and all the different providers. They all have their own secret sauce for figuring out what is spam, and it's based on a lot of flags. Also based on what people mark as spam as well. And what SendGrid does is it really tries to understand that and do some of the hard work for you and also give you insights and literally tell you this is what you're doing wrong. This is what you should do to increase deliverability. Sometimes there's some really, really easy wins that you can just get straightaway, which is really nice as well. Things like making sure that your account is coming from a right email, not a spoofed email, like you said. Because all of these things, they add credibility when you're going through that inbox of the person you're trying to reach, making sure you don't end up in spam. Also, like you said, having that weight of we are SendGrid and we do a lot of work to make sure all of the emails sent from our platform are not spam or are not sort of malicious, I would say. Because of that, we also gain extra credibility as well.
JASON: Nice, nice, nice. I'm trying to get -- I'm being forced to do two-factor auth, so everybody hold, please, while I get that set up.
NATHANIEL: See, now we can shame Jason.
JASON: I'm sorry.
NATHANIEL: But honestly, this has happened to me on stream. I hoped a new like Twilio account. Sometimes I do a hard refresh on my demo account. (Music)
JASON: I deserve that.
NATHANIEL: I forgot how much the audience gets involved. All right. Here we go.
JASON: So now I have a code. And that code is here. Whoops.
NATHANIEL: Using 2FA to keep it all in the family. You don't have to use Authy.
JASON: Wait, I did. I just put in the code. What are you doing?
NATHANIEL: Did you get the one from your email? Oh, wait. There you go. You're in. Oh, it looked like you were in.
JASON: Okay. So I'm here. Clicking the button, right.
JASON: Two-factor auth. I got a code. And now I'm going to continue. You better work. Yo! What are you doing? What are you doing to me?
NATHANIEL: That's weird.
JASON: Okay. Let's maybe clear things because I must have broken something. So we'll just --
NATHANIEL: I'm pretty sure you've logged on before, right?
JASON: Yeah, it even says set up 2FA required, false. Killing me. Killing me. All right. So I'm just going to take all of this and get rid of all the data. No more data. Now we're going to reload. Oh, wait. Redirect to log out. That's what happened. I got caught in some weird loop where I was on the logout page, and it redirected me to the log-in page. Then it redirected me to the log-out page. So that's my own fault for doing goofy things with the way that this works. So let's get one more code in here. It's going to work for sure this time. Eh? Hey!
NATHANIEL: Drum roll, yes.
JASON: So now I have things. It's all working. Everything is doing what I want. Chat was already on this, if we'd been paying attention.
NATHANIEL: Someone is ringing my doorbell. Do you mind giving me two secs while I quickly go and sort that out?
JASON: Absolutely, yes.
NATHANIEL: I'm not expecting anyone or anything, but give me a second.
JASON: All right. So while Nathaniel becomes a starry sky for us, we'll just dig in here and look a little bit. So what I've been using is I did a little bit of this ahead of time because when you're setting up domains, you need to make sure that the domains are clear. And I need to find -- here, mail settings. So in order for me to -- no, that's not the one. Sender authentication. So you have to actually, like, have an authenticated domain. To do that, I will just click this button so everybody can see it. We'll just do a different one. Would you like to brand the links for this domain? I don't care. Hey, he's back. I was showing how to do the domain authentication.
JASON: So if we want to send from like jamstackconf.com. We don't need a return path. So we hit next, and it'll give us that set of names we can use. I've already done this. So if I go back to my settings and sender authentication, it'll show me two, and I can delete this one. So now I have my one domain set up and configured. This is the stuff you have to do to avoid spam. That's what we're talking about, right?
NATHANIEL: Because what you can do is -- what you'll see there is when we're using the API, you can specify this is the email address I want to send from. But from this email, but it really came from this other email, which will be like SendGrid or have SendGrid in there as well. What you want it to do is to really have it authentically coming from you. That's why we bring that in.
JASON: Yeah, and it's really great to be able to do that because, you know, first of all, I don't trust emails that come from not the domain that it sent from. Phishing 101 in any corporate security training is like, hey, if the email comes from somebody and you don't recognize the domain, probably throw it in the trash. (Laughter) So it's good to be able to send from your own domain. It's especially good when that comes in with a -- like, it's trustworthy. You have proven I own this domain. I can modify the domain records. That's how we know this is actually from who it says it's from. So I have that set up. So what do I need to do next?
NATHANIEL: Now what you would need to do is get API keys so that we can use them within our code. So that we can write code that would send an email.
JASON: I'm going to start off screen in case it shows the keys. It doesn't, okay. We're coming back. You can see your API key. I already created one of these so I could put it into the app ahead of time so we wouldn't have to wait to make that happen.
NATHANIEL: Environment variables.
JASON: Exactly. We got our environment variables set up.
NATHANIEL: I feel like we're doing good. Any stream where we've gone X minutes without doxxing ourselves is always a win.
JASON: I'm very happy with us for all the things we've done. I'm proud of us. (Laughter) So here's our app. I'm on the dev. I'm going to open it up. My computer is starting to chug. That's always a concerning sign. Let me run Netlify dev here. We're using Netlify CLI and Netlify dev, which will do a lot of things for us. We're able to pull in all of our secret keys that we need, including this SendGrid API key. Xander, look at you go. Ten subs. I love it. Thank you so much. Welcome, everybody. Remember, there's a boop emote that I haven't seen yet. All y'all just got access to it. So you can get aggressive.
NATHANIEL: Are we going to get buried in boops?
JASON: We're going to find out. So here's our setup here. We've got our local host. Now we're running the site. It's up on local host 8888. It's letting our functions load in the background. So we've got a proxy server set up for that. We've got the site running locally so that we can do all that dev. Here we go. Here we go.
NATHANIEL: I told you. The moment you called that out, I was like you are asking to be buried. It's not a Learn With Jason if I don't get buried in boops at some point.
JASON: (Laughter) Okay. So now we're running. That means that we can start setting up function. So the function that I want to set up is called send confirmation.
JASON: So I already installed -- just, again, because I wasn't sure how much time we were going to have and I didn't want to get us in trouble, I installed the SendGrid mail package, which is an npm package for the SendGrid SDK. I don't know how this works. I just installed it.
NATHANIEL: There's actually so many different -- I think when people think about SendGrid, they only think about, okay, I'm going to send an email. But there's actually so much you can do. You can parse emails coming in. You can handle like contacts as well. So there's almost different parts of the library for that. So we're just focused on sending mail for now.
JASON: Absolutely. Yeah, we're definitely doing the original use case, not the only use case.
JASON: Okay. So --
NATHANIEL: Do you want to go and get your API key?
JASON: Yeah. So it's already in. That is going to be process.env.SendGrid API key.
NATHANIEL: We want to add it to mail, so we set the API key using, like -- mail should have a method called set API key. So if you --
JASON: Oh, yep. There it is. Here's our autocomplete. Just like this?
JASON: All right. So at this point, we're authenticated. SendGrid knows who we are. So we can just do stuff.
NATHANIEL: Awesome. And what we probably want to do is let's say we want to just -- let's just practice sending an email when this function runs. Then it's pretty simple. I think we stick it in a tri-catch because any time there's an API, there's a small chance that things might not work. But what we'll do is -- and you've got this synchronous function, which is perfect for this. I like to use a wait. We can just say, like, mail.send await.
JASON: Okay, that's great. We get here. Message is error sending email. Then in here, we're going to await mail.send. Okay. And we can see here that we've got some autocomplete happening. So data, if I open this up, I can hit control space to get our autocomplete because TypeScript is magic. We can just start seeing what's happening here. So that seems like an email field.
NATHANIEL: From is going to be the email that we set up already.
NATHANIEL: Or the email domain. For example, we might have a email@example.com.
JASON: Okay. So let's do that.
NATHANIEL: It's also going to be who you're sending to. Usually what you'd have is whatever event that triggers this function will have some information. Like, yo, this is the email of the person. So we just hard code it for now. Let's send it to you.
JASON: Actually, I'm going to send it to an inbox I can show on screen. So let's go firstname.lastname@example.org, because that's an empty inbox I can actually show.
NATHANIEL: Then you get a subject.
JASON: Subject line. And this can just be whatever we want. So, you made a -- let's see. Someone claimed some swag.
NATHANIEL: Whoop-whoop! And rather than a body, you have two kind of options. You can go with text, which this is the written text. Or you can go with HTML. I'm pretty sure we've seen fancy emails with all the different styling that HTML has to offer. We can do that and just put in HTML tags. You don't need to worry about body and everything. Think of this as everything that would live within that body.
JASON: Okay. So we can do, like -- let's do like an H3 and we'll say someone claimed Jamstack Conf swag. We'll say H3, and then someone out there is looking fly. Then we can make this, like -- I don't know. We'll just link to our site so that we can look at it. Here's -- not that one. Not that one. Not that one. Oh, I'm in the wrong -- oh, that's why this is weird. I'm in the wrong window.
JASON: Here, this one. So a link to this. I don't know why you would link to the site that you definitely built. Then we can do our closing paragraph tag. And that's an email. Okay. So we've got a basic email going here. Then when we're done, we got to -- whoops. We got to send --
NATHANIEL: Just return. Yo, this worked. Probably 1 or 200. And there we go. And this is like my favorite thing about SendGrid. Just to be honest, Twilio APIs as a whole. The one caveat is you have to go and do a little bit of setup to make sure you're coming from an authenticated email address, from like an official email address. Other than that, there's always just really, really simple, like, pieces of code, only a few lines of code that go into whatever you're building as well. You know what, I see dominuskelv is going ahead of what we're doing. I do want to talk about templates. Pretty cool.
JASON: Yeah, so let's do this. Let's get this thing sending. Then we will -- I mean, honestly, it should be -- we should have this sending as soon as Postman loads. So once this loads for us, we can go to -- what did we call this one? Send confirmation. Whoops, whoa. Oh, release notes. So send confirmation. Then if I send this as a get request because we didn't send any -- like, we're not using any. Get is the simplest. So let's send it. It says email sent. So I'll go over to my email and switch to this inbox. And hey, hey. Look at that.
NATHANIEL: Someone claimed some swag.
JASON: We got some swag. And look, my heading is bolded. We've got some text here. We've got a link. The link worked and opened in this browser over here. So we can see that. Also, check this out. It has a Jamstack Conf click thing. So it's actually part of the Jamstack Conf setup. It's like I'm clicking on my own URL, which is -- and I'm pretty sure I can change that URL to be, like, my own thing, right? So it could be like email.jamstackconf.com or something.
NATHANIEL: Yeah, absolutely.
JASON: So, this is really powerful. I have one more thing I want to do, though. Can I make this, like, come from a name?
NATHANIEL: I believe you can. I don't think I've done it myself. But give me a second. What we actually do is we would -- when we come from, we would put something in front of it. Give me one second. I'm going to quick look this up.
JASON: So I know how I do this in like, Gmail. So I'm going to try what I would do in Gmail and see if it works. Like, this is my suspicion. If we do it like this, because this is like the node thing and it's like the standard thing. So let's just see.
NATHANIEL: So this will add a name to that email. And it should appear as Jamstack. This is the thing, we're so used to --
JASON: Ta-da! And what I like about that is because I've seen this format before from writing my name is JSON, this is how you would specify it. This is how I do it when I'm trying to send emails and I want it to show up in my address book later. I'll write somebody's name and email address like this. So it was really intuitive. It worked the way I expected it to work, which is really nice. That also means that if we were getting somebody's information, like we get a payload from whatever webhook we're using, I could also format this to send it to their name at their email, and not have to do anything fancy. I just drop it in, like this would be the name variable, this would be the email variable, and we're off to the races.
JASON: That is really slick. Like, that's so nice to use.
NATHANIEL: And so this is just a simple transaction. This is what I often think of the most basic version of SendGrid. But what happens is a lot of times, for example, you want to have a designer maybe design the app or someone else design the app. All you want to do is maybe give that design some sort of parameters. Say, here is the name, here are these things. Then what you can do is when you send that off, you would actually have a template set up on SendGrid. You can have it so it just goes and says, okay, go grab this template. Put in the name, put in these other details, and then create an email with that template. So you can have like a designer work on it while you just write the code.
JASON: That's cool. Jordan just asked if it does reply to. I just tested it while you were explaining that, and it does, indeed, do a reply to. So I set the reply to here. It comes from no reply. But it replies to real email. When I hit the replay button, it showed up as real email. If we look in here, we can see that it was sent from no reply. So it's doing what we expected, all those things work the way we want them to. So that's always good news. Okay. So if we want to use those templates, we got 26 minutes. You think we can do it?
NATHANIEL: 26 minutes?
JASON: Let's see how far we can get.
NATHANIEL: Yeah. I feel like I've slowly learned over my development career that any time someone says can we do it in X amount of time, I'm always like -- uh. Before, I was like absolutely. Now, let me think first. But yeah, if you go over to the design library --
JASON: We got a SendGrid fan.
NATHANIEL: This is where you can create your email designs. What's cool is you can use a code editor or a design editor. So the design editor is kind of drag and drop, no-code solution. But even if you use the design editor, all it does is generates HTML that you can then edit on the fly as well.
JASON: Oh, nice. Okay. That'll probably be faster then. We can probably do something quick we are the design editor.
JASON: Okay. So I'm going to click on this. Here's my email. Here's an unsubscribe block. Need one of those. We need build. Okay. So let's do an image. Drag and drop your images here. Let's go to Unsplash and get -- always a Corgi. Oh, that's how I'm going to feel at the end of this week when I am done with nine streams? Eight streams? A lot of streams. So we're going to put this into my downloads folder. Then we can drag -- where did you go? Here. Here's our Corgi. So we're going to put this Corgi right in there, insert it. Then what? We want some text or maybe we do columns.
NATHANIEL: We can do columns. You can now more add terms within them.
JASON: So good. So I'm happy about that. That all looks good. I'm going to add text in this one. Then actually, why don't I just drag this one? Can I move this one in here? I need to get to the dragger bar, don't I? Dragger, hello?
NATHANIEL: Drag it down, all the way down.
JASON: There. Okay. So now this should be -- let's see. Do I change it here? How do I --
NATHANIEL: You want to change the text?
NATHANIEL: Click on it. There you are. Like start typing.
JASON: Oh, I was already in it. So intuitive I didn't even notice. Let's see. So you made a -- someone claimed some swag let's celebrate by looking at this Corgi. Okay. So this is my -- whoops. That's not the button I was supposed to push. I'm going to save this. Oh, do I need a subject and stuff?
NATHANIEL: Yeah, yep. What you can do is still parse these things in. If you go back one --
NATHANIEL: There you go, yep. And what's also cool is you actually have -- you can use, like, handlebars to add in all of your dynamic data whenever you're typing. So let's say you wanted to bring in something, you can use handlebars, which is pretty cool.
JASON: Okay. So I got that. I'm happy with that.
NATHANIEL: Call. And should we test it? If you click on the test your email.
JASON: Yes. So we'll go to -- so that's the email we'll send it to.
JASON: Oh, this is the from email. Okay. So we need email@example.com.
NATHANIEL: Yep. And you're going to send a test message.
JASON: Let's do it. My test message has been sent. Okay. Cool, cool, cool. I think my -- there it is. My email was too zoomed in for the columns to work. That's also good to know that it flows and doesn't just blow out and cause me to side scroll. But this is great. Now I've got the ability to unsubscribe. I've got my unsubscribe preferences. Good, good, good. This is great. Like, this is doing exactly what we want it to do. So how would I actually use this?
NATHANIEL: So there is another parameter which lets you specify which template you want to use. If you go back on top left, that back button --
NATHANIEL: You should be able to get an identifier from this. So go to edit. What we want is we want the -- oh, we've got the name. Cool. You've got the design name. That's what we need.
JASON: This one?
NATHANIEL: Yep, this is the one we need. And what we do is we then go over to our code. Then we just use that. We actually specify which template we want to use.
JASON: Okay. So do I get rid of all of this then?
NATHANIEL: No, you still want your from. You still want your to. Then what you're going to do -- just give me a second.
JASON: Template ID was an autocomplete. Then do I just feed it this?
NATHANIEL: I'm trying to remember where to get the template ID from.
JASON: So there's like this up here. Is that the template ID?
NATHANIEL: I don't think so.
JASON: This is private to your account and only visible to you.
NATHANIEL: Sorry, the whole thing has been redesigned. Go to build, if you don't mind. The build tab. Is this you or me that's got OneDrive that isn't signed in?
JASON: Oh, that's me. Sorry.
NATHANIEL: No worries.
JASON: So we've got email body, content container, tag. Library, your images. Preview, duplicate, single send.
NATHANIEL: Give me a moment. I'm just going to figure out where that is, where to find that ID. Once we have the ID, we just stick it in, and that's it. We've got everything. We have personalizations.
JASON: Okay. I'm going to just experiment while you're looking. I'm going to try by name. Because that would be dope if it was smart enough to do that. So let's see. This is probably going to fail. No, okay. So that one doesn't work. Let's try this ID up here. That looks like a unique identifier. I'm going to drop this in here. And send. Hey, that one looked like it worked. Let's see what happens.
NATHANIEL: That does look like what they do look like.
JASON: So if that worked, it should come in here. Momentarily.
NATHANIEL: Go back to your template.
JASON: I did send it to myself, right? Back to my template or --
NATHANIEL: The template on SendGrid.
NATHANIEL: If you close preview, look at the bottom of the page. If you click on edit, and right at the bottom -- there used to be a button. Click on test your email. Where's it gone? Give me one moment.
JASON: Is it -- like, am I too zoomed in? No, it's not that.
NATHANIEL: I don't believe so.
JASON: It said it sent, but it didn't actually arrive. So I wonder if -- I must have just sent it like an invalid ID and it ignored it.
NATHANIEL: I've lost the template design. Dynamic template, my bad. I got it mixed up.
JASON: It's okay. We still have a few minutes left. We can do this again.
NATHANIEL: So we use the same thing for marketing -- for the marketing product. And I got the UIs mixed up.
JASON: So this is the template ID.
NATHANIEL: That's the template ID. I was like, where has it gone?
JASON: Okay. This should now work, right?
NATHANIEL: Now you can select that design, yep.
JASON: So I'm going to send this version.
NATHANIEL: But if you go back, you need to specify the design that we'll use.
JASON: I do?
NATHANIEL: The add version. Click on the version, and click on the design. Oh, okay.
JASON: I think this is just to make a version of it.
NATHANIEL: Oh, okay. My bad. Yeah, you're right. You're right.
JASON: Let's see. It's going to do it this time. I believe. Come on. Do the thing. Here. Hey! Look, it came in. It's using the right header. Now let's see if I reply, it's still using my reply to header. So all of the things that we wanted to happen are happening. And that happened fast enough that we can actually try to put some stuff in here. So what if we want -- what if I want to put in some, like, handlebar stuff? Can I define custom things and feed them in through my template?
NATHANIEL: Yes, you can.
JASON: Like if I wanted it to be something cool, can I specify something cool?
NATHANIEL: What you would do is when you're writing your code, you're going to add something cool to personalizations.
JASON: Okay. And if I want to do a personalization, is that in here somewhere?
NATHANIEL: No, it's in your code editor.
JASON: In my code editor, okay. So I go -- oh, wait, wait, wait. You mean this code editor.
NATHANIEL: Yeah, in your -- yeah, there you go.
JASON: Gotcha. And is this an object?
NATHANIEL: Is personalizations right? Or are you missing a comma?
JASON: I think it's spelling that it doesn't like. So if I just put in something cool and --
NATHANIEL: So the personalization, then it goes to a very specific -- yep.
JASON: Did I do it?
NATHANIEL: The personalizations can then be used in your template. If you give me a moment, let me quickly find it.
JASON: It would be really cool if this just worked. Just like spamming myself with emails to try this. This is how email design always goes for me. I end up sending myself a hundred emails. So I did something wrong because it doesn't like my personalizations for some reason. I should log the actual error, huh.
JASON: So let's try that. Let's run this and go to the logs. And it says array expected for personalizations. That's okay. We can do that.
NATHANIEL: Then it's going to have a to. So who the first one is going to go to.
JASON: In the personalizations?
JASON: Um, I should probably look this up, right? What section of the API, so that I'm not making you dictate this to me.
NATHANIEL: No worries. How to send an email with dynamic templates. I've just sent it in our Zoom chat so you can grab it.
JASON: Okay. I got to do that through -- dynamic transactional templates.
NATHANIEL: My bad. I should have done it --
JASON: All good, all good. So I have an API key. Dynamic transactional templates. Then down to these personalizations. All right. So this is going to do -- we've got the from email. We've got the personalizations. We have a template ID. Then it's letting us do -- ah-ha. Okay. So we start here. And we do a to. The to is going to be -- we'll just move this one down. All right. So we've got that. Then it wants dynamic template data. So I will give it that. And that is also an object.
NATHANIEL: Now you can use your custom, whatever field you want. So it could be something cool now.
JASON: Okay, so I do that. Good. Then where does it show me in the template?
NATHANIEL: We then want to use handlebars in our template.
JASON: So that part I was right on. Where is it? Here. So just this?
NATHANIEL: Should be something cool, I believe.
JASON: Nice. So we've got this. We've got something cool. Dynamic template data. And that, theoretically, should do the thing. Send. Email sent. Hey, hey! All right.
NATHANIEL: Drum roll.
JASON: And show new messages.
Show me potato salad.
JASON: Let's see. It came back empty. I did something wrong. Are there rules about naming? Dynamic transactional templates. Dynamic template data.
NATHANIEL: Where did we have it? In the design is what I mean.
JASON: I put it into -- wait. Here. In the design, I put it in here.
NATHANIEL: Something cool. Did it not like the fact that we've -- if you close that -- if you hit the X on this text module and go to build, is there anything to do with data coming in? No.
JASON: Let's see if we can preview. Yeah, it doesn't show test data. Must be formatted as JSON.
NATHANIEL: So you can stick in that JSON. So put in there something cool.
JASON: Okay. So if I get it in right, it should work. Let me just check that we didn't --
NATHANIEL: It just did there.
JASON: Yeah, so it does it right in the preview, which means that I'm not sending it right in the code. So dynamic template data.
NATHANIEL: Change dynamic template data to -- without underscores and capital Ts. We took the docs from, like, just creating -- try that.
JASON: You're right. The autocomplete.
NATHANIEL: When we copied it over, it was using curl rather than the Node library.
JASON: Oh, I got you.
NATHANIEL: There's a different set of -- what's the word? Things that you're supposed to do with naming conventions.
NATHANIEL: There we go.
JASON: We got it. I mean, this is amazing. I love that we were able to do this that fast. We've got dynamic content coming in. So we can send in anything here. We could say what somebody bought. We could say what time it is. Like, we could do all sorts of stuff. Because this is all handled in a serverless function, you know, we can figure any day it we want up here. Hey, let's calculate anything, and then we can drop it in here.
NATHANIEL: But what's also cool is if you remember the personalizations, it was to each individual. So what you can do is with one API call, you can send personalized emails to multiple people, right. So let's say you wanted to send something to a group of people, you would have the from and the reply to and the rest of the things. Then you'd bring in the template. And for the personalization, you would then iterate that array at the bottom. Exactly.
JASON: Okay. Let's do this. Let's do one. Then we can do an email. Let's see. We got seven minutes. We can get this happening. Support@learnwithjason.dev. So here's our emails. And you're saying here --
NATHANIEL: Now when we go down to our personalizations, you see here how we've got an array of objects, right. So all we need to do is hand it people.
NATHANIEL: Or we can do something to map an array. Exactly.
JASON: Okay. So we're going to send back person name. And person email. Right?
JASON: Then we can also say, like --
NATHANIEL: Wow name. Okay, yep. Greeting.
NATHANIEL: Did you close the map? Like the open parentheses?
JASON: And I'm beach balling. There we go. Okay. So that should be working. Now if I go back in here, I can go to design, click on this. And let's pass in greeting. Right? Save that. And then when we go out here and actually run -- oh, let me make sure I didn't crash. Nope, it's all good. So then I'm going to send. Error sending email. What didn't you like? It says bad request 400? Did I get rate limited? That can't be right. Authorization on behalf of, body errors array. So I probably need to get into that body errors. Let's do that. So what is it? It's error.response.body.errors. I want to just try this one more time. Okay. Now it should have logged something a little bit -- the to array is required for all personalization objects and must have at least one email with a valid email address.
NATHANIEL: Have you got an array within an array? This may be me being silly. When you did person maps to -- no, no.
JASON: Yes, you're absolutely right. I'm returning -- yep. Good call. Okay. So what I need to return instead is just the object.
JASON: So we can make that an object. We can make that an object. And now we get an array. Okay. So let's try that one more time. Good catch. That would have taken me the rest of the episode. Email sent. Okay.
NATHANIEL: It's one of those things where I've gone through it before.
JASON: Hey. All right. And then I'm going to take this off screen so I can open up the one in my own inbox because I don't know what else is in here. And here's the one to me. This came in with all the stuff we wanted. It's got the no reply. It came to my email. It's got the personalization in place. Like, that's slick. That's really, really slick.
NATHANIEL: So, the cool thing is now in your hands, what you want to do with it, how you want to sort of make it basically whatever you want to build. It's now up to you. Also, I love the fact you have the unsubscribe buttons that you can then link to other things as well. It gives you some of that functionality out of the box already.
JASON: Yeah. I mean, it's just a nice -- like, it all feels good. Right? Like what we're getting here is, you know, we didn't have to do very much work. We were able to customize this very quickly. We got our email templates in place. We're sending something that's designed. So if we work with our design team, we could get something that really looked nice, and all of the text could be dynamic. Like, we could make this a header and some body text and then, like, whatever our sideline is, like maybe our top articles. You can do some really incredible stuff here that I think is so powerful.
NATHANIEL: Especially when you're working with a bigger company, when you've got more people wearing different hats. You are the developer. You want to send the email. You don't care about what -- well, you may not personally care about what the email looks like. Then you have a designer which loves that but doesn't care about getting the data from the database and making sure everyone gets the right thing. You can just both work together seamlessly.
JASON: And as long as you agree on this, like this is your API contract, right. If they use these handlebar templates, you can feed whatever data you want into that thing. And it's just nice. Like, it's a nice experience.
NATHANIEL: Is this the first time we've actually finished our project on a stream? Or second? I think it might be first or second.
JASON: You're not wrong. (Laughter)
NATHANIEL: Because I'm always talking way too much.
JASON: I love it so much.
JASON: Nathaniel, we're actually going to focus and build the thing.
JASON: Everybody, please go and click, click, click on the follow button on Nathaniel's profile. Check out twitch.TV/Twilio. And also, head over to this swag app here and get yourself one of those swag packs. They're 25% off.
NATHANIEL: And fill Jason's emails with notifications from SendGrid.
JASON: Yes, please do it. We didn't actually set up the webhook for this. So to actually make it --
NATHANIEL: Ah, dang it.
JASON: That's okay. I don't actually need these emails. But you know, to do it, we would just go to Shopify and set up a webhook that would call our serverless function. A lot of places have event-driven hooks. We call them like build hooks where you can call a serverless function when a thing happens. That's a really powerful way to go.
NATHANIEL: And this is just sending, right? So then we also have like an inbound pass where you can set up a webhook for what happens when you receive an email address. Maybe you want to do some fancy stuff with it. Maybe push it to someone else or read the content, and based on the reply, send it to the right place as well. Lots of awesome stuff you can do.
JASON: Absolutely. All right, y'all. We're going to take a short break. Nathaniel, thank you so much for your time today. This was an absolute blast. We're going to come back in 13 minutes with Ben Vinegar from the Sentry team. Don't go anywhere. We're not even going to turn the stream off. We'll see you in 13 minutes. Thanks again, see you in a minute.