Product
Docs
Resources
Log InSign Up

Balance what's good for your product and delightful for your users.

Courier helps manage the complex logic of delivering notifications.

Request a demo

Twitch Notifications Part 2 Header
ENGINEERING

Twitch Notifications (Part Two): How to Send Notifications When Your Twitch Stream Goes Live

Aydrian Howard

January 28, 2021

In this series, I explain how to use Twitch EventSub and Courier to automatically send notifications to multiple destinations – Slack, Discord, and more – when your Twitch stream goes live.

In part one, we built a Node.js app using Express.js to accept events from Twitch EventSub. Now, in part two, we’re going to listen for our event and trigger a notification using Courier.

Follow along with the series:

Need help getting started with sending notifications about your Twitch stream? Join our community on Discord – we’re happy to chat!

How to send notifications when your Twitch stream goes live

In this tutorial, I’ll show you how to take the Node.js and Express app that we built in part one and use it to listen for our events. From there, we’ll create and trigger a notification in Courier. I’ll demo sending an SMS notification with Twilio, but you can use Courier to send notifications to any channel, including popular chat apps like Discord and Facebook Messenger.

Prerequisites

To complete this tutorial, you'll need a few things:

If you’re using the Node.js and Express.js app we created in part one, it should either be deployed somewhere publicly accessible that supports HTTPS and port 443, or be running locally using ngrok.

We'll use a new or existing Twitch application from your Developer Console along with the Twitch CLI to subscribe to the stream.online event and point it to the /webhooks/callback route on our server. Then, we'll update our server code to capture that event and send it to Courier to create and send the notification.

Keep in mind that there could be around a 45 second delay before Twitch triggers the event from the time your stream goes online.

Step one: Subscribe to the Twitch EventSub online event

To begin receiving requests from Twitch EventSub, we first need to create a subscription. We'll use the Twitch CLI to create a Stream Online subscription type and give it the callback URL from our Node.js application. It's important that the application is running and publicly available because EventSub will attempt to validate the callback URL when creating the subscription.

Configure the Twitch CLI

First, we need to configure the Twitch CLI using a new or existing Twitch application. If you have already configured your Twitch CLI, you can skip this step.

Navigate to the Twitch Developer Console and create a new by clicking “Register Your Application” or open an existing application. Add [http://localhost:3000](http://localhost:3000) as an OAuth Redirect URL.

Twitch Developer Application

Take note of the Client ID, as we'll be using this shortly. You'll also need to generate a new Client Secret by clicking on the “New Secret” button. Be sure to save this somewhere safe because it won't be shown again. If you have an existing Client Secret for this application, you can use it. Generating a new secret will invalidate any existing secret.

Now, let's use these values to configure the Twitch CLI. In a terminal, run the following command:

1
twitch configure

You will be prompted to enter your Client ID and Secret. To fetch an access token, run the following command:

1
twitch token

You're now ready to start making Twitch API calls using the Twitch CLI.

Subscribe to the Stream Online Event

To create our Stream Online subscription, we'll use the Twitch CLI to POST to the EventSub Subscriptions endpoint.  You'll need to provide the full URL for your webhook callback, the secret value set in the TWITCH_SIGNING_SECRET environment variable of your Node.js application, and your Twitch broadcaster user ID.

To find your broadcaster user ID, run the following command replacing trycourier with your Twitch login ID:

1
twitch api get users -q login=trycourier

Twitch CLI Get User

This will output your Twitch user object in JSON format. Your broadcaster user ID will be the ID.

Now let's create the subscription. Run the following command with the needed substitutions:

1
twitch api post eventsub/subscriptions -b '{
2
"type": "stream.online",
3
"version": "1",
4
"condition": {
5
"broadcaster_user_id": "YOUR_BROADCASTER_ID"
6
},
7
"transport": {
8
"method": "webhook",
9
"callback": "https://EXTERNAL_URL/webhook/callback",
10
"secret": "YOUR_SECRET"
11
}
12
}'

Twitch CLI Create Subscription

You should see “Verification successful“ in the console of your running application. Every time you go online, your application will now receive a POST with a payload similar to the following:

1
{
2
"subscription": {
3
"id": "5d179ae7-d744-45a4-a259-5129634dd788",
4
"type": "stream.online",
5
"version": "1",
6
"condition": {
7
"broadcaster_user_id": "493127514"
8
},
9
"transport": {
10
"method": "webhook",
11
"callback": "https://15a1265bdd3c.ngrok.io/webhook/callback"
12
},
13
"created_at": "2021-01-26T17:15:17Z"
14
},
15
"event": {
16
"id": "9001",
17
"broadcaster_user_id": "493127514",
18
"broadcaster_user_login": "trycourier",
19
"broadcaster_user_name": "TryCourier",
20
"type": "stream.online"
21
}
22
}

Now we can update our application to accept and process this event.

Step two: Capture the event and send it to Courier

Now that we’ve created our Stream Online subscription, the next step is to send it to Courier, which we’ll use to create and deliver notifications about our Twitch stream. To do this, we need to add a call to Courier's Send API when a stream.online event comes in. We'll use the Courier Node.js SDK to do this. We'll also use the Twitch.js library to query the Twitch API to grab more details about the stream that we can send to Courier.

First, let's add these npm packages and configure the necessary environment variables.

Gather your environment variables

We've reached a point where we are using enough environment variables that we should use a better method of loading them. Let's create a .env file and use the dotenv package to load them when the application starts.

Create a .env file with the following:

1
TWITCH_SIGNING_SECRET=purplemonkeydishwasher
2
TWITCH_CLIENT_ID=your-twitch-client-id
3
TWITCH_CLIENT_SECRET=your-twitch-client-id
4
COURIER_AUTH_TOKEN=your-courier-auth-token

Use the Twitch values from step one of our tutorial. You can find your Courier Auth Token in Settings > API Keys in your Courier account. Use the Published Production Key.

Now let's install the dotenv package, along with the other packages mentioned above:

1
npm install dotenv @trycourier/courier twitch

And add the following line to the top of your index.js:

1
require("dotenv").config();

Now when you run your application, these values will be loaded and ready for your application to use.

Process the stream.online event

Let's continue updating our application by running a function when the type of the event is stream.online.

Just below the console.log in the /webhooks/callback handler, add the following:

1
if (type === "stream.online") {
2
try {
3
sendOnline(event);
4
} catch (ex) {
5
console.log(
6
`An error occurred sending the Online notification for ${event.broadcaster_user_name}: `,
7
ex
8
);
9
}
10
}

Next, let's create sendOnline as an async function. This function will handle grabbing any additional information about the Twitch stream and sending it to Courier.

Add the following to the top of index.js with the rest of the require statements:

1
const { CourierClient } = require("@trycourier/courier");
2
const courier = CourierClient();
3
const { ApiClient } = require("twitch");
4
const { ClientCredentialsAuthProvider } = require("twitch-auth");
5
const authProvider = new ClientCredentialsAuthProvider(
6
process.env.TWITCH_CLIENT_ID,
7
process.env.TWITCH_CLIENT_SECRET
8
);
9
const twitch = new ApiClient({ authProvider });

This will create the Courier and Twitch clients we'll use in the sendOnline function. Add the following function to your application:

1
const sendOnline = async event => {
2
const stream = await twitch.helix.streams.getStreamByUserId(
3
event.broadcaster_user_id
4
);
5
const game = await stream.getGame();
6
7
const { messageId } = await courier.send({
8
eventId: "TWITCH_ONLINE",
9
recipientId: "AYDRIAN10036",
10
profile: {
11
phone_number: "+12025550140"
12
},
13
data: {stream, game}
14
});
15
console.log(
16
`Online notification for ${event.broadcaster_user_name} sent. Message ID: ${messageId}.`
17
);
18
};

This function will use the Twitch client to grab information about the stream such as the title and game info and then pass it to the call to Courier's Send API so it can be used in the creation of your notification. You'll also want to update the recipientId to a unique string – I used my name and zip in all caps without spaces: AYDRIAN10036 –  and the  phone_number with your phone number. You’ll need both of these in order to receive the notification we create in Courier.

The next time you go online, the stream.online event will flow into Courier. Next, we'll use the stream information to create a notification using Courier's template builder.

Step three: Create your notification in Courier

For this tutorial, we'll be creating a text notification for our Twitch stream. We'll explore other notification channels in the third part of this series.

Configure Twilio as your SMS provider

Let's start by configuring the Twilio integration in Courier. This will require you to enter details about your Twilio account. Check out our Getting Started with Twilio guide for more details.

Twilio integration

Design your SMS notification

Now it's time to design the notification in Courier. Navigate to the Notification Designer and select “Create Notification.” Click “Untitled Notification” on the top left to give your notification a descriptive name – in this case, I’ve named mine “Twitch Online Alert.”

Now let's add SMS as a channel for our notification by selecting SMS and choosing Twilio from the dropdown. We can now select SMS under Channels to the left and start designing our notification.

Create SMS Notification

We'll design a simple SMS notification. First, we'll use a text block – click the “T” on the toolbar – and add the following text: “{stream._data.user_name} is playing {game._data.name} on Twitch.“ Next, we'll add another text block with the following text: “{stream._data.title}.” And we'll add one more text block with the following text: “https://twitch.tv/{stream._data.user_name}“. We’re personalizing the SMS using the stream information, which we passed to the notification in the data object as part of calling the Courier API.

SMS Notification Designer

This is enough for now, but feel free to add more content blocks and continue designing the SMS message. When you’re finished, click “Publish Changes” in the upper righthand corner.

If you’d like, you can preview the email using the Preview tab and ensure your variables are templated properly. You'll be prompted to Create a Test Event and then you'll want to update the JSON object with the following example, replacing the phone_number with your own:

1
{
2
"data": {
3
"stream": {
4
"_data": {
5
"id": "40078987165",
6
"user_id": "493127514",
7
"user_name": "trycourier",
8
"game_id": "417752",
9
"game_name": "Talk Shows & Podcasts",
10
"type": "live",
11
"title": "Courier Live: Twitch EventSub and Courier",
12
"viewer_count": 0,
13
"started_at": "2021-01-05T19:54:35Z",
14
"language": "en",
15
"thumbnail_url": "https://static-cdn.jtvnw.net/previews-ttv/live_user_trycourier-{width}x{height}.jpg",
16
"tag_ids": null
17
}
18
},
19
"game": {
20
"_data": {
21
"id": "417752",
22
"name": "Talk Shows & Podcasts",
23
"box_art_url": "https://static-cdn.jtvnw.net/ttv-boxart/Talk%20Shows%20&%20Podcasts-{width}x{height}.jpg"
24
}
25
}
26
},
27
"profile": {
28
"phone_number": "+12025550140"
29
}
30
}

Once you save your test event, you should see the name variable populate in the Preview tab with whatever value you’ve set.

Map your notification to the event specified in your Send call

The last thing we want to do is to map the event we specified earlier in the Courier Send call to this notification. Next to the notification name, click the gear icon to launch the Notification Settings. Select Events from the left menu and enter “TWITCH_ONLINE” in the Events box.

Map notification

Close the dialog and your notification is ready to send. If you don't want to wait for the next time you go online, you can test your notification using the Send Tab.

We can now test our application using the Twitch CLI. Run the following command with the needed substitutions:

1
twitch event trigger streamup --to-user YOUR_BROADCASTER_ID -F https://EXTERNAL_URL/webhook/callback -s YOUR_SECRET

This command will trigger an example stream.online event using your broadcaster id. You should see the event in the Courier Logs and receive an SMS message.

Putting it all together: Full application code

With all the new updates, your finished application should look like the following.

1
require("dotenv").config();
2
const express = require("express");
3
const crypto = require("crypto");
4
const { CourierClient } = require("@trycourier/courier");
5
const app = express();
6
const port = process.env.PORT || 3000;
7
const twitchSigningSecret = process.env.TWITCH_SIGNING_SECRET;
8
const courier = CourierClient();
9
const { ApiClient } = require("twitch");
10
const { ClientCredentialsAuthProvider } = require("twitch-auth");
11
const authProvider = new ClientCredentialsAuthProvider(
12
process.env.TWITCH_CLIENT_ID,
13
process.env.TWITCH_CLIENT_SECRET
14
);
15
const twitch = new ApiClient({ authProvider });
16
17
app.get("/", (req, res) => {
18
res.send("Hello World!");
19
});
20
21
const verifyTwitchSignature = (req, res, buf, encoding) => {
22
const messageId = req.header("Twitch-Eventsub-Message-Id");
23
const timestamp = req.header("Twitch-Eventsub-Message-Timestamp");
24
const messageSignature = req.header("Twitch-Eventsub-Message-Signature");
25
const time = Math.floor(new Date().getTime() / 1000);
26
console.log(`Message ${messageId} Signature: `, messageSignature);
27
28
if (Math.abs(time - timestamp) > 600) {
29
// needs to be < 10 minutes
30
console.log(
31
`Verification Failed: timestamp > 10 minutes. Message Id: ${messageId}.`
32
);
33
throw new Error("Ignore this request.");
34
}
35
36
if (!twitchSigningSecret) {
37
console.log(`Twitch signing secret is empty.`);
38
throw new Error("Twitch signing secret is empty.");
39
}
40
41
const computedSignature =
42
"sha256=" +
43
crypto
44
.createHmac("sha256", twitchSigningSecret)
45
.update(messageId + timestamp + buf)
46
.digest("hex");
47
console.log(`Message ${messageId} Computed Signature: `, computedSignature);
48
49
if (messageSignature !== computedSignature) {
50
throw new Error("Invalid signature.");
51
} else {
52
console.log("Verification successful");
53
}
54
};
55
56
const sendOnline = async (event) => {
57
const stream = await twitch.helix.streams.getStreamByUserId(
58
event.broadcaster_user_id
59
);
60
const game = await stream.getGame();
61
62
const { messageId } = await courier.send({
63
eventId: "TWITCH_ONLINE",
64
recipient: "AYDRIAN10036",
65
profile: {
66
phone_number: "+12025550140"
67
},
68
data: { stream, game }
69
});
70
console.log(
71
`Online notification for ${event.broadcaster_user_name} sent. Message ID: ${messageId}.`
72
);
73
};
74
75
app.use(express.json({ verify: verifyTwitchSignature }));
76
77
app.post("/webhooks/callback", async (req, res) => {
78
const messageType = req.header("Twitch-Eventsub-Message-Type");
79
if (messageType === "webhook_callback_verification") {
80
console.log("Verifying Webhook");
81
return res.status(200).send(req.body.challenge);
82
}
83
84
const { type } = req.body.subscription;
85
const { event } = req.body;
86
87
console.log(
88
`Receiving ${type} request for ${event.broadcaster_user_name}: `,
89
event
90
);
91
92
if (type === "stream.online") {
93
try {
94
sendOnline(event);
95
} catch (ex) {
96
console.log(
97
`An error occurred sending the Online notification for ${event.broadcaster_user_name}: `,
98
ex
99
);
100
}
101
}
102
103
res.status(200).end();
104
});
105
106
const listener = app.listen(port, () => {
107
console.log("Your app is listening on port " + listener.address().port);
108
});

Our application will now process stream.online events and pass them to Courier along with additional stream data. Courier will then create an SMS notification and send it.

So, what's next?

In the next post, we'll explore other types of notifications and how to use Courier to send to them all at the same time. In the meantime, take a look at the different integrations available in Courier and see if you can update your application to support a new one. Join our Discord community and let me know which one you're most interested in!

-Aydrian

Balance what's good for your product and delightful for your users.

Courier helps manage the complex logic of delivering notifications.

Request a demo

More from Engineering

serverless-lie-detector-thumbnail
ENGINEERINGINTEGRATIONS

Create a Discord Bot that Automates Secret Messages with Node.js

Our plan is to create and install a Discord bot that automates encrypted messages to the civilians and alerts them about the situation so that they can escape.

Shreya Gupta

Shreya Gupta

September 27, 2022

serverless-lie-detector-thumbnail
ENGINEERINGINTEGRATIONS

Build a Serverless Lie Detector that uses AI for Facial Recognition

When the Face API recognizes that one of our spies is being deceitful, we will use Courier to broadcast the identity of the mole to our spy network.

Shreya Gupta

Shreya Gupta

September 12, 2022

Build your first notification in minutes

Send up to 10,000 notifications every month, for free.

Get started for free

Email & push notification

Build your first notification in minutes

Send up to 10,000 notifications every month, for free.

Get started for free

Email & push notification

Product

Pricing

Providers

Developers

Documentation

API

Libraries

Status

© 2022 Courier. All rights reserved.