What I have learned of building a chatbot in GatsbyJS, Contentful and Ninetailed

Tags: webdev, javascript, personalization, cms
Published: 2021-04-06 12:32:34

To begin with, building a Chatbot with [GatsbyS](https://www.gatsbyjs.com/) and [Contentful](https://www.contentful.com/) may appear strange, but it all began with a customer personalization exercise and experiment at my company [Ninetailed](https://www.ninetailed.io/).

And, spoiler alert, our GatsbyJS, Contentful, and Ninetailed based Chatbot works great and, more importantly, it was fun and quick to develop (we finished it in a couple of hours).

##GatsbyJS, Contentful & Ninetailed - An Introduction

We use GatsbyJS for our website ninetailed.io because it is great for creating lightning-fast, accessible, and SEO-friendly websites. It is also easy to use and integrates seamlessly with our headless CMS Contentful.

Ninetailed, on the other hand, is a personalization and optimization platform for modern websites. Not to mention that Ninetailed has a [GatbsyJS plugin](https://www.gatsbyjs.com/plugins/@ninetailed/gatsby-plugin-ninetailed/) and a [Contentful App](https://www.contentful.com/marketplace/app/ninetailed-personalization) to make integration in this stack simple and quick.
Personalizing our website with a Chatbot

We had the idea to integrate a chatbot with the Ninetailed personalization platform during a brainstorming session about personalization experiences. An interactive chatbot is ideal for gathering information from visitors such as intent, job roles, and adapting website content to user data and intent. As a result, the content journey and customer experience are enhanced.

The next step is to select a Chatbot solution. There are numerous advanced Chatbot solutions available, such as Solvemate or Intercom, that combine the power of natural language processing (NLP), rule-based conversations, and human operators.

Following our API-first, rapid prototyping, and agile development philosophy, we decided to create a prototype using our personalization API and SDKs. After all, we want to personalize our website based on visitor intent, and our personalization engine can handle rule-based audiences.

##Let's build a chatbot

For our website stack we use GatsbyJs, Contentful, Tailwind CSS and Ninetailed for website personalization. This stack will serve as our starting point...

###1. Chatbot flow
First and foremost, we define the chatbot flow. We keep things simple because we're working on a prototype. In this first iteration, we use a decision tree model with two steps and two data points or user traits:

* The first step is to request the first name in order to personalize the page and create a demo effect. This also personalizes the guide experience, and we want to highlight our merge tag personalization feature.
* The second step is to inquire about the visitor's role. This allows us to match the visitor to one of our personas and adapt the website's content. The role is an important aspect of our marketing personas, as it relates to the visitor's intent.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bl5xritmkk8v3ducm1ke.png)
<figcaption>Chatbot flow</figcaption>

###2. Chatbot UI
Because we use Tailwind UI as design system, creating chatbot UI elements like the bubble and chat window is simple and quick.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/f87x8i8bn7x5m0mtk68d.png)
<figcaption>Chatbot UI example</figcaption>

###3. Contentful content model
We create a new content model in Contentful with the following fields:

* Name used as entry title.
* Image for the chatbot
* Message for the chatbot.
* Placeholder for the input field.
* Button text for the button.
* Event ID to define the event to send with the value of the input. 

We have a lot of flexibility with this content structure because we can create the chatbot content within Contentful CMS without changing any code and adapt the content variants for personalization with the Ninetailed Personalization App.

###4. Ninetailed personalization
Finally, integrating the code with Ninetaled takes only a few minutes because we only need to wrap the chat component with the `<Personalize />` component (and install the GatbsyJS plugin if you haven't already).

####Chatbot component code example:

``` typescript
import React from "react";
import { ChatFragment } from "../../../@generated/types";
 
import { ChatApiProvider } from "./ChatApiProvider";
import { Container } from "./Container";
import { Body } from "./Body";
import { Launcher } from "./Launcher";
 
export const Chat: React.FC<ChatFragment> = (props) => {
 return (
   <ChatApiProvider>
     <Container>
       <Body {...props} />
       <Launcher />
     </Container>
   </ChatApiProvider>
 );
};
```

####Ninetailed personalization code example:
``` typescript
import React, { useEffect } from "react";
import { GatsbyImage, getImage } from "gatsby-plugin-image";
import { Form, Field } from "react-final-form";
import {
 Profile,
 useAnalytics,
 useProfile,
} from "@ninetailed/client-sdk-react";
import { createRenderNinetailedMergetag } from "@ninetailed/client-sdk-gatsby-contentful";
import { BLOCKS, INLINES, MARKS } from "@contentful/rich-text-types";
import { Options } from "@contentful/rich-text-react-renderer";
import { Link as GatsbyLink } from "gatsby";
 
import { ChatFragment } from "../../../@generated/types";
 
import { renderRichText } from "../RichText";
import { sanitizeSlug, Link } from "../Link";
import { useChatApi } from "./ChatApiProvider";
import { CloseButton } from "./CloseButton";
 
const options = (profile: Profile): Options => ({
 renderNode: {
   [BLOCKS.PARAGRAPH]: (node, children) => (
     <p className="text-sm text-gray-500">{children}</p>
   ),
   [INLINES.HYPERLINK]: (node, children) => (
     <a
       href={node.data.uri}
       target="_blank"
       className="text-indigo-600 hover:text-indigo-500"
     >
       {children}
     </a>
   ),
   [INLINES.ENTRY_HYPERLINK]: (node, children) => (
     <GatsbyLink
       to={sanitizeSlug(node.data.target?.slug)}
       className="font-medium text-indigo-600 hover:text-indigo-500"
     >
       {children}
     </GatsbyLink>
   ),
   [INLINES.EMBEDDED_ENTRY]: (node, children) => {
     if (node.data.target.__typename === "ContentfulLink") {
       return (
         <Link
           className="inline-flex my-2 mr-2 items-center px-2.5 py-1.5 border border-transparent text-xs font-medium rounded shadow-sm text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"
           {...node.data.target}
         />
       );
     }
 
     return (
       <span className="mr-1">
         {createRenderNinetailedMergetag(profile)[INLINES.EMBEDDED_ENTRY](
           node,
           children
         )}
       </span>
     );
```
###5. Variants and audiences
In Contentful, we must now create variants and specific audiences for the chatbot content. It only takes a few clicks to create personalization variants with Ninetailed and Contentful. If the visitor has filled out a first name and has chosen a role in the chatbot, we create a variant for the chat message.

We use user traits and events for the audiences:

* Visitors who have filled out their first names.
* Visitors who have chosen a role.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wlna1mt10nfzpttteqzv.png)
<figcaption>Audience first name</figcaption>

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gg19n3w1q5ylwm6od83f.png)
<figcaption>Audience developers</figcaption>

##Learnings and next steps 

This chatbot integration took us only a few hours to complete. It was not only quick to make, but also enjoyable to work on. This prototype project demonstrated:

* Working with your own stack and product must be exciting.
* Think outside the box and be inventive in the application of your own product.
* Developer experience with your stack and tools is critical.
GatbsyJS, Contentful and Ninetailed have an excellent developer experience.
* A design system enables rapid prototyping.

As the prototype was successful in development, and after a week, the chatbot's engagement rates are great, we intend to:

* Add more steps to the chatbot flow.
* Integrate more powerful chatbots.
* Create SDKs or integrations with chatbots.

Finally, please let me know what you think about this chatbot prototype and how we used GatsbyJS, Contentful, and Ninetailed to create it. If you want to create a similar chatbot or customize your Contentful website with personalized content, you can install the Ninetailed app for free from the [official marketplace](https://www.contentful.com/marketplace/app/ninetailed-personalization).