Chat widget Medusa plugin
Medusa 2.0 commerce platform plugin to integrate Chat Widget for seller/buyer communication
With the plugin, store owners can:
- add live chat support to help customers in real-time
- enable buyer-seller messaging in multi-vendor marketplaces
- support group conversations or private threads
- record and persist messages securely via ConnectyCube’s backend
Use cases:
- Customer Support: Enable users to ask questions and get support without leaving the site
- Marketplace Messaging: Let buyers and vendors chat directly in a secure environment.
How can I use it?
On storefront, once logged in and opened product page, there will be a Chat toggle button bottom right:
Once clicked, a chat with seller will be opened where you can ask any product’s related questions:
From Medusa dashboard there will be a new page called Chat, with the widget embedded, where all customers’ chats are displayed, so you as a merchant can reply:
Installation
Backend
-
Add plugin to your Medusa 2.0 core app:
yarn add @connectycube/chat-widget-medusa-plugin -
Create ConnectyCube account https://connectycube.com/signup and application, obtain credentials
-
Add the following variables to your
.env
file:VITE_BACKEND_URL=http://localhost:9000VITE_CHAT_APP_ID=<YOUR CONNECTYCUBE APP ID>VITE_CHAT_AUTH_KEY=<YOUR CONNECTYCUBE AUTH KEY>VITE_BACKEND_URL
- The URL of your Medusa backend, required for custom admin components.VITE_CHAT_APP_ID
- This is essential for authenticating your application with the ConnectyCube platform and accessing its chat services.VITE_CHAT_AUTH_KEY
- This key is used to authorize your application and ensure secure communication with the ConnectyCube SDK.
-
Add the following code to your
medusa-config.ts
file:module.exports = defineConfig({admin: {vite: (config) => {config.define["__VITE_CHAT_APP_ID__"] = JSON.stringify(process.env.VITE_CHAT_APP_ID);config.define["__VITE_CHAT_AUTH_KEY__"] = JSON.stringify(process.env.VITE_CHAT_AUTH_KEY);return {optimizeDeps: {include: ["qs", "eventemitter3", "@xmpp/iq/callee", "@xmpp/resolve", "@xmpp/session-establishment", "@xmpp/client-core", "@xmpp/sasl-plain", "@xmpp/stream-features", "@xmpp/resource-binding", "@xmpp/reconnect", "@xmpp/middleware", "@xmpp/sasl-anonymous", "@xmpp/websocket", "@xmpp/iq/caller", "@xmpp/sasl"], // Will be merged with config that we use to run and build the dashboard.},};},},projectConfig: { ... },plugins: [{resolve: "@connectycube/chat-widget-medusa-plugin",options: {},},],})This code connect plugin and helps to resolve an issue similar to https://github.com/medusajs/medusa/issues/11248.
-
Start the project:
Terminal window yarn dev
Storefront
-
Add chat widget to your Storefront app:
yarn add @connectycube/chat-widget -
Add the following variables to your
.env
file:NEXT_PUBLIC_CHAT_APP_ID=<YOUR CONNECTYCUBE APP ID>NEXT_PUBLIC_CHAT_AUTH_KEY=<YOUR CONNECTYCUBE AUTH KEY>NEXT_PUBLIC_STORE_ID=<YOUR MEDUSA STORE ID>NEXT_PUBLIC_STORE_NAME=<YOUR MEDUSA STORE NAME> -
Create
src/ChatWidget.tsx
component with the following content:"use client"import React, { useEffect, useState } from "react"import ConnectyCubeChatWidget from "@connectycube/chat-widget/react19"import { StoreCustomer, StoreProduct } from "@medusajs/types"export interface ChatWidgetProps {customer: StoreCustomer | nullproduct: StoreProductchatPerProduct?: boolean}export default function ChatWidget({customer,product,chatPerProduct,}: ChatWidgetProps) {const quickActions = {title: "Quick Actions",description:"Select an action from the options below or type a first message to start a conversation.",actions: ["Hi, I'm interested in this product.","Can you tell me more about the price and payment options?","Is the product still available?","Can I schedule a viewing?",],}if (!customer) {return null}const [defaultChat, setDefaultChat] = useState<any>(null)const [isOpen, setIsOpen] = useState<boolean>(false)const onOpenCloseWidget = (isOpen: boolean) => {setIsOpen(isOpen)}const storeId = process.env.NEXT_PUBLIC_STORE_IDconst storeName = process.env.NEXT_PUBLIC_STORE_NAMEuseEffect(() => {if (isOpen) {console.log("Widget is open:", isOpen)const defaultChatKey = chatPerProduct ? product.id : storeIdconst defaultChatName = chatPerProduct ? product.title : storeNamesetDefaultChat({id: defaultChatKey,opponentUserId: storeId,type: "group",name: defaultChatName,})}}, [isOpen])return (<div><ConnectyCubeChatWidget// credentialsappId={process.env.NEXT_PUBLIC_CHAT_APP_ID}authKey={process.env.NEXT_PUBLIC_CHAT_AUTH_KEY}userId={customer.id}userName={`${customer.first_name} ${customer.last_name}`}// settingsshowOnlineUsersTab={false}splitView={true}// quick actionsquickActions={quickActions}// notificationsshowNotifications={true}playSound={true}// moderationenableContentReporting={true}enableBlockList={true}// last seenenableLastSeen={true}// url previewenableUrlPreview={true}limitUrlsPreviews={1}// attachments settingsattachmentsAccept={"image/*,video/*,.pdf,audio/*"}// default chatdefaultChat={defaultChat}onOpenChange={onOpenCloseWidget}/></div>)} -
update
tsconfig.json
:{"compilerOptions": {"module": "nodenext","moduleResolution": "nodenext",...}} -
update
storefront/src/app/[countryCode]/(main)/products/[handle]/page.tsx
to retrieve customer info and pass it toProductTemplate
:const customer = await retrieveCustomer()return (<ProductTemplateproduct={pricedProduct}region={region}countryCode={params.countryCode}customer={customer}/>) -
Finally, connect
ChatWidget
component on product details page, e.g.src/modules/products/templates/index.tsx
<ChatWidgetcustomer={customer}product={product}chatPerProduct={true}/>
Demo
The complete demo app (backend + storefront) available https://github.com/ConnectyCube/chat-widget-medusa-plugin-demo-app
Have an issue?
Join our Discord for quick answers to your questions or file a GitHub issue