How to Integrate Discord as Notification Provider in Medusa
Tags: javascript, webdev, programming, opensource
Published: 2022-10-20 11:00:00

[Medusa](https://medusajs.com/) is an open source headless commerce platform. It is an alternative to Shopify, especially for developers who want more customization and control over their ecommerce websites.

Medusa has organized a hackathon to run through October 2022. You can win awesome prizes by building ecommerce projects using Medusa. You can learn more about it by visiting this page: [Medusa Hackathon sign-up: Win Merch and Prizes up to $1,500 During Hacktoberfest](https://dev.to/medusajs/medusa-hackathon-sign-up-win-merch-and-prizes-up-to-1500-during-hacktoberfest-4h45).

In this tutorial, you’ll see a submission example for the hackathon. You’ll learn how to use Medusa’s customization capabilities to set up Discord as the notification provider. A message will be sent to the Discord server when a new order is placed.

You can find the code for this tutorial in [this GitHub repository](https://github.com/surajondev/medusa-discord-integration).

## Prerequisites

Ensure these tools are installed on your machine:

- [NodeJS](https://nodejs.org/en/download/): It is a JavaScript runtime build. You need to have at least v14 of NodeJS to run commands for installing packages and the Medusa server.
- [Git](https://git-scm.com/downloads): It is an open source version control system. Medusa uses Git behind the scenes while creating a Medusa project.
- Medusa CLI: It will be used while running the Medusa server on a local machine. Install the CLI by running the command below after installing NodeJS:

```bash
npm install @medusajs/medusa-cli -g
```

- [Redis](https://docs.medusajs.com/tutorial/set-up-your-development-environment/#redis): It is an in-memory data structure store and message broker. Medusa uses Redis as the event queue in the server.

## Install Medusa

The process of installing Medusa is quite simple; you just need to run a single command on the terminal. Run the below command to start installing Medusa:

```bash
npx create-medusa-app
```

After running the command, you need to enter the name of the project. By default, it’s `my-medusa-store`. Hit enter once you choose the name for your project. 

Now, you need to choose the Medusa starter. Choose the `medusa-starter-default`.

After this, you need to choose the storefront server. You have options such as Next.js starter, Gatsby starter, and others. Choose a starter that you are comfortable with; I chose the `Next.js starter`.

After choosing all this, the installation process will move forward. All the necessary dependencies for your project will be installed. After completion of the installation, you will have these three directories inside the `my-medusa-store`:

- **storefront**: This is the frontend of your store, which is created with the framework you chose during the installation process.
- **backend:** This is where all the magic happens; it has the code for your Medusa server.
- **admin:** It is the place for the seller. It helps in managing the products, offers, payments, and other seller-related features. It is made in Gatsby. You need not change anything in the admin codebase.

## Configure Redis

Redis runs locally and we need to add the URL of the server to the project. Go to `backend/medusa-config.js` and add `redis_url: REDIS_URL` into the `projectConfig`. By default, `REDIS_URL` is set to `redis://localhost:6379`:

```jsx
module.exports = {
  projectConfig: {
    //...
    redis_url: REDIS_URL // Redis URL 
  },
  plugins,
};
```

After all this, the setup is now done. Now, it's time to set up the webhooks in our Discord server. 

## Create Discord Webhook

Discord webhook is a way of sending messages from a third-party integration or application to the Discord server. A webhook is like a member of the server with a name and profile picture. This webhook will post messages coming from the other application.  

Let’s set up the Webhook on our server.

Click on your server name at the top-left corner, then choose server settings. In the server settings, click on the `Integration` tab from the left panel.  The integration panel lets you manage webhooks and bots of your server.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/evw9cq4ncdnsvf4cy0a7.png)

Click on **Create Webhook** to create a random webhook. 


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/n993rxxuwxyfwhxmyeda.png)

You can edit it to display the profile pic, name, and channel in which messages will be posted. After editing the webhook, click on **Save Changes**.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0etrpm6k8pz4dgxew7ee.png)

Here is the `Order Notification` webhook that will post messages in the general channel. 

At the bottom of the webhook, you can see the `Copy Webhook URL` button. Click on it and copy the URL of the created webhook. Now go to `backend/.env/` and add the URL as the environment variable:

```
DISCORD_WEBHOOK_URL="discord_webhook_url"
```

## Implement Discord Notification Provider

Let’s first understand how the notification provider works in Medusa. Whenever an event occurs in the Medusa server, such as a product added to the cart or an order placed, the event is passed into the event bus and directed to the notification plugin. 

First, let’s create the notification provider that will have the `discord-notification` as an identifier and run when someone places an order. 

Go to `/backend/src/services` and create a file with the`discord.js` name. Here, you’ll define the function to run when someone places the order. 

Place the following code inside the file:

```jsx
import axios from 'axios';
import {NotificationService} from 'medusa-interfaces'

class DiscordNotification extends NotificationService {
    static identifier = "discord-notification";
    constructor({ orderService }) {
      super();
      this.orderService_ = orderService;
    }
    async sendNotification(eventName, eventData) {
        if (eventName === 'order.placed') {
          //retrieve order
          const order = await this.orderService_.retrieve(eventData.id, {
            relations: ['items']
            }
          )

        const URL = process.env.DISCORD_WEBHOOK_URL

        let content = `New Order Placed⚡\nNumber of products: ${order.items.length}`
        const embeds = []
        
        
        order.items.map(item => {
          content += `\n\nProduct : ${item.title} \nQuantity : ${item.quantity} \nDescription:${item.description}`
          embeds.push({
            image: {
               url: item.thumbnail
            }
          });
        })

        await axios.post(URL, {
          content,
          embeds
        })

        return {
          to: URL,
          data: {
              content,
              embeds
          }
        };
        
    }}}

  export default DiscordNotification;
```

You name the class `DiscordNotification` and it extends the `NotificationService`. In the constructor, you can access different services in Medusa. In this case, you access `orderServices` that contains data regarding the orders. 

You add an asynchronous function with the name `sendNotificaiton`. At the top of the function, there is the code to verify whether the event is `order.placed` or not. If it is, then, you’ll proceed further. 

After that, the order ID is retrieved from `eventData` and the full details of the order are retrieved using the `orderService` and stored in the `order` variable.

In the next step, you’ll access the webhook’s URL from the environment and store it in the `URL` variable. You then initialize two variables: `content` is for the text that contains information about the order and `embeds` for the image of the product.

You’ll use the map function to iterate over the order items. In the map function, you are concatenating the previous string of `content` with the new item's data. In `embeds`, you are pushing the URL of the image. After the loop, you use Axios to send a request to the Discord webhook to send the message to the server. 

In the end, an object with two properties will return: `to` and `data`[.](http://data.to)  

- `to` contains the medium of notification, which is Discord in our case. Therefore, the URL of the webhook is given.
- `data` contains the message that was sent to Discord.

This will create a notification record in Medusa’s database. 

You then must subscribe to the `order.placed` event with a subscriber. For this, create a subscriber that calls the `notificationService.subscribe` function.

To create a subscriber, go to the `/backend/src/subscribers` directory and create a file with the`discord.js` name with the following content:

```jsx
class DiscordNotification {
  constructor({ notificationService }) {
    // Subscribe to order.placed events
    notificationService.subscribe("order.placed", "discord-notification");
  }
}

export default DiscordNotification;
```

The subscriber calls `notificationService.subscribe` in the constructor. It takes two arguments: the first is the name of the event and the second is the name of the identifier. The notification provider that has the `discord-notification` identifier is subscribed to the `order.placed` event.

## Test the Integration

The project has been completed and it’s time to see it work live. 

### Run the Environment

First, run the Medusa server, storefront, and Redis server. 

**For Backend:**

Go to `backend/` and run the Medusa server with the below command:

```bash
npm run start
```

**For Storefront:**

Change to the `storefront` directory and add the command below to run Medusa’s storefront at `localhost:8000` by default:

```bash
npm run dev
```

### Place an Order

If your storefront runs well, you will be able to see the storefront on the `localhost:8000`. Select the product and click on checkout from the cart. Now, fill in the shipping details. The details need not be accurate as you are only testing. Select the fake delivery options and payment will be already completed for testing. 


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zqrrhws9lnzs0aa9sygh.png)

After filling in the details, click on the `Checkout` button on the right-side panel. If everything goes well, your order will be placed. 


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/n5aeo6bhnzp5opnw14xq.png)

The notification regarding the order will be sent to your Discord server. 


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cfisq77567y5eruonvrw.png)

## Conclusion

Using Medusa’s plugin system, you can integrate any third-party service and tool for different purposes such as Notifications, Payment, or CMS. You can also publish your plugins for the community to use and benefit from.

If you’re interested in seeing more Medusa plugins, check out the [Integrations page](https://www.notion.so/1a0ada9903874e0185d0b8ce0591b359). You can also learn more about [plugins in the Medusa documentation](https://docs.medusajs.com/advanced/backend/plugins/create/).

> Should you have any issues or questions related to Medusa, then feel free to reach out to the Medusa team via [Discord](https://discord.gg/F87eGuwkTp).