Tutorials

Broadcast Trading & Stock Market Messages to Multiple Users at Fixed Times | Using Node.js and SuprSend

July 8, 2023
Learn how to build a stocks information broadcasting system. Integrate the SuprSend API, set logic and subscriber lists, and send timed broadcasts to users.
TABLE OF CONTENTS

Project Details

Stocks information broadcasting project will walk you through the steps to build a broadcasting system for your stocks and trading application. You would be able to integrate the SuprSend API in your application, set broadcasting logic and subscriber lists, and run timed broadcasts to those subscribers.

Preview

Deployed Link: Stock Alerts (stockmarketsuprsend.onrender.com) 
Github Repo Link: SuprSend-NotificationAPI/Stocks-information-broadcast (github.com)  

Application Features

  • Add Subscribers: You can add subscribers from the application’s front end, and update it automatically on SuprSend application using Lists API
  • Remove subscribers: You can remove subscribers from the application’s front end by passing the distinct_id of the user which will remove the subscriber from the List on SuprSend. 
  • Real-time stock updates: Using Alphavantage API we would be receiving real-time stock notifications of US stocks. 
  • Sending Broadcasts: Sending broadcasts on your real-time subscriber list from the application’s frontend which calls SuprSend’s Broadcast API. It is an important use case of all stocks trading/ algo trading applications where updating users with real-time stock information is required at set times.
  • Users can Subscribe/ Unsubscribe: Users can subscribe or unsubscribe to the stock updates as per their wish directly from the application’s frontend. Moreover you can use SuprSend Preferences to automatically remove a user from receiving notifications of specific models. 

Technology Stack

  • Frontend: EJS, Javascript
  • Backend: Node.js
  • Database: MongoDb
  • Notification API: SuprSend 
  • Stocks API: Alphavantage

File structure

Frontend (UI/ UX)

You can find the frontend HTML part in here: Stocks-information-broadcast/views at main · SuprSend-NotificationAPI/Stocks-information-broadcast · GitHub

You can find the frontend CSS styling code in here: Stocks-information-broadcast/public/css at main · SuprSend-NotificationAPI/Stocks-information-broadcast (github.com)


You can use and modify the above code to suit your design ideas. Let’s check how our frontend UI will look like:

Homepage

This is our landing page when someone clicks and lands on our deployed URL. It contains the app functionalities along with our website link and project’s Github repository. 

A screenshot of a stock alertDescription automatically generated with medium confidence

Add subscribers page 

With this functionality you can create multiple subscriber to which notifications would be sent. Businesses can also use our API to create subscriber lists programmatically

A screenshot of a formDescription automatically generated with low confidence

Broadcast Testing

If a tester wants to test the broadcast message then he/she needs a key otherwise he/she cannot send the broadcast message.

Unsubscribe Link

User can also unsubscribe the plan and he will not receive any further updates. For that he just need to type in his/her distinct user id generated at SuprSend.

Backend Codes and Integrations

We would be using MongoDb database to store users and their other important permissions.

models/user.js

Coding Block Example
Copied ✔

const mongoose = require('mongoose');
const {Schema, model} = mongoose;


const UserSchema = new Schema({
  username: {type: String, required: true},
  name : String,
  phone : {type:Number},
});


const UserModel = model('User-stock', UserSchema);


module.exports = UserModel;

    

Setting up the backend

You can find the WORKSPACE_KEY and WORKSPACE_SECRET on the ‘Settings’ tab on SuprSend application, once you signup

Coding Block Example
Copied ✔

require("dotenv").config()
const express = require("express")
const mongoose = require("mongoose")
const bodyParser = require("body-parser") 
const User = require("./models/user")
const { Suprsend, SubscriberListBroadcast } = require("@suprsend/node-sdk");


const app = express();
app.set('view engine', 'ejs');
app.use(bodyParser.urlencoded({extended:true})); 
app.use(express.static("public"));


mongoose.set('strictQuery', true);
const uri = process.env.MONGO_URI;
mongoose.connect(uri, {useNewUrlParser: true});


const workspace_key = process.env.WORKSPACE_KEY;
const workspace_secret = process.env.WORKSPACE_SECRET;
const supr_client = new Suprsend(workspace_key, workspace_secret);

    

Creating ‘List’ On SuprSend

The Lists SDK methods lets you create a list of subscribers. You can then send bulk messages to all the subscribers in the list with a single API call.

Coding Block Example
Copied ✔

const subscriber_lists = supr_client.subscriber_lists.create({
    list_id: "stocksubscribers",
    list_name: "Stock Subscriber",
    list_description: "This list contains the information of the the all the ids which are subscribed to the stock market site "
});

    


You can create multiple lists on the application, all of which would be visible in the ‘Subscribers’ section on the application. Using the List_id  you can use our API to broadcast notifications to that particular subscriber list. It would look like:

You can toggle inside a list, and check out the subscribers inside that list, add, delete or update that subscriber information from our dashboard. Each subscriber is mapped to a distinct_id which would then be used for any debugging process. 

Getting routes <index.js>

Coding Block Example
Copied ✔



app.get("/",(req,res)=>{
    res.render("homepage")
})


app.get("/createuser",(req,res)=>{
    res.render("userpage");
})


app.get("/broadcastinput",(req,res)=>{
  res.render("inputkey");
})


app.get("/removeuser",(req,res)=>{
  res.render("inputuser");
})




/************post routes**********/
    

Post routes

Coding Block Example
Copied ✔


app.post("/add-user",(req,res)=>{
    const{usermail,username,userphone} = req.body;
    const newUser = new User({
        username: usermail,
        name : username,
        phone : userphone
    })


  const distinct_id = usermail; 
  const user = supr_client.user.get_instance(distinct_id)
  user.add_email(usermail)
  user.add_sms(userphone);


  const response = user.save()
  response.then((res) => console.log("response", res));
  
  const data = supr_client.subscriber_lists.add("stocksubscribers", [
     distinct_id
  ]);
  data.then((res) => console.log(res)).catch((err) => console.log(err));
  res.redirect("/");
})


/**app.post("/sendnotification", async (req, res) => {*/

    


With this we added users to the database and that is then updated to the subscribers list. We can further setup the notification channels easily once your subscribers list is ready.

Integrating Stocks API and Implementing Notifications Broadcasting

We use the Alphavantage API to get real-time stock prices which can be replaced by your stock/ trading system. We will setup a key, which you can create of your choice, then that key would be used for authentication to send data. 

Once the key matches the data would be sent to SuprSend for broadcasting.

Coding Block Example
Copied ✔

app.post("/sendnotification", async (req, res) => {
  const {name,key} = req.body;
  console.log(name,key);
  if(key!="any key of your choice” res.send("wrong key");
  else{
  const request = require('request');
  const getData = (symbol) =>{ 
    const url = `https://www.alphavantage.co/query?function=TIME_SERIES_DAILY_ADJUSTED&symbol=${symbol}&apikey=${akey}`;
    return new Promise((resolve, reject) => {
      request.get({
        url: url,
        json: true,
        headers: { 'User-Agent': 'request' }
      }, (err, response, data) => {
        if (err) {
          reject(err);
        } else if (response.statusCode !== 200) {
          reject(new Error(`Status: ${response.statusCode}`));
        } else {
          const firstData = data['Time Series (Daily)'][Object.keys(data['Time Series (Daily)'])[0]];
          resolve(firstData);
        }
      });
    });
  };
  
  try {
    const symbol = ["IBM","TSCO.LON","SHOP.TRT","GPV.TRV","DAI.DEX","RELIANCE.BSE"]
    const data1 = await getData("IBM");
    const data2 = await getData("TSCO.LON");
    const data3 = await getData("SHOP.TRT");
    const data4 = await getData("GPV.TRV");
    const data5 = await getData("DAI.DEX");
    const broadcast_body = {
      list_id: "stocksubscribers",
      template: "broadcast-message",
      notification_category: "transactional",
      channels: ["email","whatsapp"],
      data:{
       'v1': {
        'Open': data1['1. open'],
        'Close': data1['4. close'],
        'High': data1['2. high'],
        'Low': data1['3. low'],
        'Split Coefficient': data1['8. split coefficient']
      },
      'v2': {
        'Open': data2['1. open'],
        'Close': data2['4. close'],
        'High': data2['2. high'],
        'Low': data2['3. low'],
        'Split Coefficient': data2['8. split coefficient']
      },
      'v3': {
        'Open': data3['1. open'],
        'Close': data3['4. close'],
        'High': data3['2. high'],
        'Low': data3['3. low'],
        'Split Coefficient': data3['8. split coefficient']
      },
      'v4': {
        'Open': data4['1. open'],
        'Close': data4['4. close'],
        'High': data4['2. high'],
        'Low': data4['3. low'],
        'Split Coefficient': data4['8. split coefficient']
      },
      'v5': {
        'Open': data5['1. open'],
        'Close': data5['4. close'],
        'High': data5['2. high'],
        'Low': data5['3. low'],
        'Split Coefficient': data5['8. split coefficient']
      }
      }
    }  
    const inst = new SubscriberListBroadcast(broadcast_body);
    const data = supr_client.subscriber_lists.broadcast(inst);
    data.then((res) => console.log(res)).catch((err) => console.log(err));
    res.render("notificationsent");
  } catch (error) {
    console.log('Error:', error);
  }
}
});

/****************** post route for unsubscribe *****************/

    

Triggering Broadcast

Use the following code to setup your backend for triggering the broadcasts. Refer to this documentation for setting broadcast feature in Node.js: Broadcast (suprsend.com) 

Setup unsubscirbe from here:

Coding Block Example
Copied ✔

const { Suprsend, SubscriberListBroadcast } = require("@suprsend/node-sdk");


const supr_client = new Suprsend(
  "_api_key_",
  "_api_secret_",
);


const broadcast_body = {...}
const inst = new SubscriberListBroadcast(broadcast_body);
const data = supr_client.subscriber_lists.broadcast(inst);
data.then((res) => console.log(res)).catch((err) => console.log(err));
    


You can use the following fields inside a broadcast body:

Once our backend is setup, we can now create notification templates that will go in the broadcast. Using SuprSend’s drag-and-drop template builder you can easily configure the templates with modern elements while using our variables to make it dynamic. 

Setting Broadcast Templates

Head to ‘Templates’ inside the application. 

Add mock data

Use the variables defined in your backend code for the stocks related information. 

Customising Template

You can customise the template with our drag-and-drop features and functions given on the right side. Once customised, you can also preview the template before saving changes. 

Your users can also unsubscribe from the broadcast list, directly by clicking on the ‘Unsubscribe’ button on the template. Or you can also unsubscribe that user from backend though a distinct_id would be needed for that user.

Coding Block Example
Copied ✔

app.post("/unsubscribe",(req,res)=>{
  const name = req.body.name;
  const data = supr_client.subscriber_lists.remove("stocksubscribers", [
     name
  ]);
  
  data.then((res) => console.log(res)).catch((err) => console.log(err));
  res.redirect("/");
})

// starting server

app.listen(3000,()=>{
    console.log("server started on port 3000");
})


    

Testing Application

Create subscribers, then head to Sending Broadcasts. Put in the unique key setup during backend implementation, and your broadcasts would be sent. You can check the broadcast analytics on SuprSend’s analytics and logs section. 

Email Your Users Receive

Using the set variable, the data is fetched in real time via the Alphavantage API and dynamically updated in the templates before sending the notifications. 

Written by:
ABOUT THE AUTHOR

What’s a Rich Text element?

The rich text element allows you to create and format headings, paragraphs, blockquotes, images, and video all in one place instead of having to add and format them individually. Just double-click and easily create content.

Static and dynamic content editing

A rich text element can be used with static or dynamic content. For static content, just drop it into any page and begin editing. For dynamic content, add a rich text field to any collection and then connect a rich text element to that field in the settings panel. Voila!

How to customize formatting for each rich text

Headings, paragraphs, blockquotes, figures, images, and figure captions can all be styled after a class is added to the rich text element using the "When inside of" nested selector system.

Implement a powerful stack for your notifications

By clicking “Accept All Cookies”, you agree to the storing of cookies on your device to enhance site navigation, analyze site usage, and assist in our marketing efforts. View our Privacy Policy for more information.