Sometimes you have done your Magento template with customizing the
search result to show nice layout with resulted products. But whoops,
your search result is not correct even though you do re-index in the
backend, clean cache and look everything around the code core. But you
are not getting correct result and you can’t find anything more to make
it work. Please try following simple way.
Goto this file \app\design\frontend\default\<your_template>\layout\catalogsearch.xml, then make sure you have added below code. (because sometime we have lacked it)
When installing the Magento 1.3.2.4, you have got this error Fatal error: Method Varien_Object::__tostring() cannot take
arguments in D:\PamySoft\Study\Magento\Magento132\lib\Varien\Object.php
on line 488 Solution to fix: 2 steps Step 1) At the file: <magento>/lib/Varien/Object.php (Line 484) Change from:
In
this tutorial, you will learn how to create a group chat app. You will
build a backend app using Node.js that will make group chats, authorize
chat participants, and maintain sessions for them. The front-end will be
built using Vanilla JS, HTML and CSS. It will allow users to log in,
make new groups, invite friends, and trade messages. By the end, you
should have a working app where multiple participants can send messages
in one group.
Chat is becoming an increasingly popular
communication medium in both business and social contexts. Businesses
use chat for customer and employee intra-company communication like with
Slack, Microsoft Teams, Chanty, HubSpot Live Chat, Help Scout,
etc. Most social networks and communication apps also offer chat as an
option by default, like on Instagram, Facebook, Reddit, and Twitter.
Other apps like Discord, Whatsapp, and Telegram are mostly chat-based,
with group chats being one of their main functionalities.
While
there exist numerous products to facilitate chat, you may need a
custom-tailored solution for your site that fits your particular
communication needs. For example, many of these products are stand-alone
apps and may not be able to integrate within your own site. Having your
users leave your website to chat may not be the greatest option as it
can affect user experience and conversion. On the flip side, building a
chat app from scratch can be a daunting and sometimes overwhelming task.
However, by using APIs like Twilio Conversations
you can simplify the process of creating them. These communication APIs
handle group creation, adding participants, sending messages,
notifications, among other important chat functions. Backend apps that
use these APIs only have to handle authentication and make calls to
these APIs. Front-end apps then display conversations, groups, and
messages from the backend.
In this tutorial, you will learn how to create a group chat app using the Twilio Conversations API.
The front end for this app will be built using HTML, CSS, and Vanilla
JavaScript. It will allow users to create group chats, send invites,
login, as well as send and receive messages. The backend will be a
Node.js app. It will provide authentication tokens for chat invitees and
manage chat creation.
Prerequisites
Before you can start this tutorial, you need to have the following:
Node.js installed. You’ll use it primarily for the backend app and to install dependencies in the front-end app. You can get it using a pre-built installer available on the Node.js downloads page.
http-server to serve the front-end app. You can install it by running npm i -g http-server. You can also run it with npx http-server for one-off runs.
MongoDB for session storage in the backend app. Its installation page has a detailed guide on how to get it running.
More after jump! Continue reading below ↓
The Backend App
To send chat messages using Twilio API, you need a conversation. Chat messages are sent and received within a conversation. The people sending the messages are called participants.
A participant can only send a message within a conversation if they are
added to it. Both conversations and participants are created using the
Twilio API. The backend app will perform this function.
A participant needs an access token
to send a message and get their subscribed conversations. The front-end
portion of this project will use this access token. The backend app
creates the token and sends it to the frontend. There it will be used to
load conversations and messages.
dotenv loads environment variables from the .env file that you will create in a later step;
express is the web framework you’ll use for the backend;
express-session provides middleware to handle session data;
http-errors helps create server errors;
morgan handles logging;
twilio creates the Twilio client, generates tokens, creates conversations, and adds participants.
Configuration
The config
folder is responsible for loading configuration from environment
variables. The configuration is grouped into three categories:
configuration for CORS, Twilio, and the MongoDB session DB. When the
environment is development, you will load config from the .env file using dotenv.
Start by creating the .env file on the terminal. This file is already added to the .gitignore file to prevent the sensitive values it contains from being checked into the repository.
touch .env
Here’s what your .env should look like:
# Session DB ConfigSESSION_DB_HOST=XXXX
SESSION_DB_USER=XXXX
SESSION_DB_PASS=XXXX
SESSION_DB_PORT=XXXX
SESSION_DB_NAME=XXXX
SESSION_DB_SECRET=XXXX
# Twilio ConfigTWILIO_ACCOUNT_SID=XXXX
TWILIO_AUTH_TOKEN=XXXX
TWILIO_API_KEY=XXXX
TWILIO_API_SECRET=XXXX
# CORS Client ConfigCORS_CLIENT_DOMAIN=XXXX
In the next step, you will get credentials from the Twilio Console. The credentials should be assigned to the variables with the TWILIO_ prefix. During local development, the front-end client will run on http://localhost:3000. So, you can use this value for the CORS_CLIENT_DOMAIN environment variable.
Add the following code to config/index.js to load environment variables.
The
environment variables are grouped into categories based on what they
do. Each of the configuration categories has its own object variable,
and they are all exported for use in other parts of the app.
Getting Twilio Credentials From the Console
To build this project, you’ll need four different Twilio credentials: an Account SID, an Auth Token, an API key, and an API secret. In the console, on the General Settings page, scroll down to the API Credentials section. This is where you will find your Account SID and Auth Token.
To get an API Key and Secret, go to the API Keys page. You can see it in the screenshot below. Click the + button to go to the New API Key page.
On this page, add a key name and leave the KEY TYPE as Standard, then click Create API Key. Copy the API key and secret. You will add all these credentials in a .env file as you shall see in subsequent steps.
The
backend app needs two utility functions. One will create a token, and
the other will wrap async controllers and handle errors for them.
In utils/token.js, add the following code to create a function called createToken that will generate Twilio access tokens:
In this function, you generate access tokens using your Account SID, API key, and API secret. You can optionally supply a unique identity which could be a username, email, etc. After creating a token, you have to add a chat grant to it. The chat grant can take a conversation service ID among other optional values. Lastly, you’ll convert the token to a JWT and return it.
The utils/controller.js file contains an asyncWrapper function that wraps async controller functions and catches any errors they throw. Paste the following code into this file:
The
backend app has four controllers: two for authentication and two for
handling conversations. The first auth controller creates a token, and
the second deletes it. One of the conversations controllers creates new conversations, while the other adds participants to existing conversations.
import{ twilioConfig }from'../config/index.js';import{ createToken }from'../utils/token.js';import twilio from'twilio';asyncfunctionStartConversation(req, res, next){const client =twilio(twilioConfig.accountSid, twilioConfig.authToken);const{ conversationTitle, username }= req.body;try{if(conversationTitle && username){const conversation =await client.conversations.conversations
.create({ friendlyName: conversationTitle });
req.session.token =createToken(username, conversation.chatServiceSid);
req.session.username = username;const participant =await client.conversations.conversations(conversation.sid).participants.create({ identity: username })
res.send({ conversation, participant });}else{next({ message:'Missing conversation title or username'});}}catch(error){next({ error, message:'There was a problem creating your conversation'});}}
The StartConversation controller first creates a Twilio client using your twilioConfig.accountSid and twilioConfig.authToken which you get from config/index.js.
Next,
it creates a conversation. It needs a conversation title for this,
which it gets from the request body. A user has to be added to a
conversation before they can participate in it. A participant cannot
send a message without an access token. So, it generates an access token
using the username provided in the request body and the conversation.chatServiceSid.
Then the user identified by the username is added to the conversation.
The controller completes by responding with the newly created
conversation and participant.
Next, you need to create the AddParticipant controller. To do this, add the following code below what you just added in the controllers/conversations.js file above:
asyncfunctionAddParticipant(req, res, next){const client =twilio(twilioConfig.accountSid, twilioConfig.authToken);const{ username }= req.body;const conversationSid = req.params.id;try{const conversation =await client.conversations.conversations
.get(conversationSid).fetch();if(username && conversationSid){
req.session.token =createToken(username, conversation.chatServiceSid);
req.session.username = username;const participant =await client.conversations.conversations(conversationSid).participants.create({ identity: username })
res.send({ conversation, participant });}else{next({ message:'Missing username or conversation Sid'});}}catch(error){next({ error, message:'There was a problem adding a participant'});}}export{ AddParticipant, StartConversation };
The AddParticipant controller adds new participants to already existing conversations. Using the conversationSid
provided as a route parameter, it fetches the conversation. It then
creates a token for the user and adds them to the conversation using
their username from the request body. Lastly, it sends the conversation
and participant as a response.
The GetToken controller retrieves the token and username from the session if they exist and returns them as a response. DeleteToken deletes the session.
In this file, the conversations router is created. A POST route for creating conversations with the path / and another POST route for adding participants with the path /:id/participants are added to the router.
Lastly, add the following code to your new routes/index.js file.
By adding the conversation and auth routers here, you are making them available at /api/conversations and /auth/token to the main router respectively. The router is then exported.
This
file starts off by creating the express app. It then sets up JSON and
URL-encoded payload parsing and adds the logging middleware. Next, it
sets up CORS and the session handling. As mentioned earlier, MongoDB is
used as the session store.
After all that is set up, it then adds
the router created in the earlier step before configuring error
handling. Lastly, it makes the app listen to and accept connections at
the port specified in the .env file. If you haven’t set the port, the app will listen on port 8000.
Once
you’re finished creating the backend app, make sure MongoDB is running
and start it by running this command on the terminal:
NODE_ENV=development npm start
You pass the NODE_ENV=development variable, so that configuration is loaded from the local .env file.
The Front-end
The
front-end portion of this project serves a couple of functions. It
allows users to create conversations, see the list of conversations they
are a part of, invite others to conversations they created, and send
messages within conversations. These roles are achieved by four pages:
The app has two dependencies: axios and @twilio/conversations. You’ll use axios to make requests to the backend app and @twilio/conversations to send and fetch messages and conversations in scripts. You can install them on the terminal by running:
You
can find the contents of these stylesheets linked in the earlier
paragraph. Here is a screenshot of what this page will look like:
The Error Page
This page is shown when an error occurs. The contents of pages/error.html can be found here. If an error occurs, a user can click the button to go to the home page. There, they can try what they were attempting again.
The Conversations Page
On this page, a user provides the title of a conversation to be created and their username to a form.
When a user clicks the Submit button, the createConversation function is called. In it, the contents of the form are collected and used in the body of a POST request made to http://localhost:8000/api/conversations/ in the backend.
You will use axios
to make the request. If the request is successful, a conversation is
created and the user is added to it. The user will then be redirected to
the chat page where they can send messages in the conversation.
When the page loads, initClient
fetches the user’s access token from the backend, then uses it to
initialise the client. Once the client is initialised, it’s used to
fetch all the conversations the user is subscribed to. After that, the
conversations are loaded onto the side-nav. In case any error occurs, the user is sent to the error page.
The setConversion function loads a single conversation. Copy and paste the code below in the file to add it:
When a user clicks on a particular conversation, setConversation is called. This function receives the conversation SID and name and uses the SID
to fetch the conversation and its messages. The messages are then added
to the chat area. Lastly, a listener is added to watch for new messages
added to the conversation. These new messages are appended to the chat
area when they are received. In case any errors occur, an error message
is displayed.
Next, you’ll add the addMessagedToChatArea function which loads conversation messages.
The function addMessagesToChatArea
adds messages of the current conversation to the chat area when it is
selected from the side nav. It is also called when new messages are
added to the current conversation. A loading message is usually
displayed as the messages are being fetched. Before the conversation
messages are added, this loading message is removed. Messages from the
current user are aligned to the right, while all other messages from
group participants are aligned to the left.
When the user sends a message, the sendMessage function is called. It gets the message text from the text area and disables the submit button. Then using the currently selected conversation, the message is sent using its sendMessage method. If successful, the text area is cleared and the submit button is re-enabled. If unsuccessful, an error message is displayed instead.
The showError method displays an error message when it is called; hideError hides it.
functionshowError(msg){
document.getElementById('error-message').style.display ='flex';
document.getElementById('error-text').innerText =`There was a problem ${msg ? msg :'fulfilling your request'}.`;}functionhideError(){
document.getElementById('error-message').style.display ='none';}
The logout
function logouts out the current user. It does this by making a request
to the backend which clears their session. The user is then redirected
to the conversation page, so they can create a new conversation if
they’d like.
Add the inviteFriend function to send conversation invites:
asyncfunctioninviteFriend(){try{const link =`http://localhost:3000/pages/login.html?sid=${window.twilioChat.selectedConvSid}`;await navigator.clipboard.writeText(link);alert(`The link below has been copied to your clipboard.\n\n${link}\n\nYou can invite a friend to chat by sending it to them.`);}catch{showError('preparing your chat invite');}}
To
invite other people to participate in the conversation, the current
user can send another person a link. This link is to the login page and
contains the current conversation SID as a query parameter. When they click the invite button, the link is added to their clipboard. An alert is then displayed giving invite instructions.
In scripts/login.js, the login function is responsible for logging in conversation invitees. Copy its code below and add it to the aforementioned file:
The login function takes the conversation sid query parameter from the URL and the username from the form. It then makes a POST request to api/conversations/{sid}/participants/
on the backend app. The backend app adds the user to the conversation
and generates an access token for messaging. If successful, a session is
started in the backend for the user.
The user is then redirected to the chat page, but if the request returns an error, they are redirected to the error page. If there is no conversation sid query parameter in the URL, the user is redirected to the conversation page.
Running the App
Before
you can start the front-end app, make sure that the backend app is
running. As mentioned earlier, you can start the backend app using this
command on the terminal:
NODE_ENV=development npm start
To serve the front-end app, run this command in a different terminal window:
http-server -p 3000
This serves the app at http://localhost:3000. Once it’s running, head on over to http://localhost:3000/pages/conversation.html; set a name for your conversation and add your username, then create it. When you get to the chat page, click on the conversation, then click the Invite button.
In
a separate incognito window, paste the invite link and put a different
username. Once you’re on the chat page in the incognito window, you can
begin chatting with yourself. You can send messages back and forth
between the user in the first window and the second user in the
incognito window in the same conversation.
Conclusion
In
this tutorial, you learned how to create a chat app using Twilio
Conversations and Vanilla JS. You created a Node.js app that generates
user access tokens, maintains a session for them, creates conversations,
and adds users to them as participants. You also created a front-end
app using HTML, CSS, and Vanilla JS. This app should allow users to
create conversations, send messages, and invite other people to chat. It
should get access tokens from the backend app and use them to perform
these functions. I hope this tutorial gave you a better understanding of
how Twilio Conversations works and how to use it for chat messaging.