El conocimiento es el nuevo dinero.
Aprender es la nueva manera en la que inviertes
Acceso Cursos

¿Cómo MEJORAR las ventas en tu negocio? Gracias a ChatGPT + Whatsapp

2:52 / 18:13 • Manychat 🤯 Instala ChatGPT en WhatsApp para VENDER MÁS y mejorar la ATENCIÓN AL CLIENTE El post de hoy se viene con tutorial, donde detallaremos acerca de como instalar chatgpt en whatsapp como una forma de mejorar las ventas y la atención al cliente.

· 13 min de lectura
¿Cómo MEJORAR las ventas en tu negocio? Gracias a ChatGPT + Whatsapp

La comunicación es clave para construir grandes marcas, en esta era digital tenemos un montón de oportunidades y formas de llevar a cabo grandes comunicaciones. Desde las redes sociales a los correos electrónicos, pasando por los mensajes de texto y las llamadas, el límite de las comunicaciones se ha puesto a prueba.

Una de las principales innovaciones en comunicación son los ChatBots.

Antes de continuar déjame recordarte que tenemos curso para que aprendas a crear tu propio chatbot de whatsapp. Te dejo el link para que puedas hacer uso de TU DESCUENTO

En pocas palabras, un chatbot es una aplicación de software utilizada para mantener una conversación de chat en línea a través de texto o texto a voz. Puede sustituir a un chat real con un agente humano.

Se ha utilizado en varios escenarios que van, pero no se limitan a los asistentes personales, atención al cliente, reserva de entradas, e-shopping, también e-banca por mencionar algunos.

Este tutorial le mostrará cómo construir un Asistente Chatbot basado en reglas utilizando Next.js y Tailwind CSS como frontend y Strapi headless CMS como backend .

Si tu quieres aprender a crear un chatbot donde hagas uso de strapi api + chatgpt esté video es para ti.

Ventajas del uso de Chatbot


Es necesario que antes de seguir avanzando en este artículo, tengamos una idea de lo que aporta un chatbot cuando se utiliza adecuadamente. Algunas de las ventajas de utilizar un chatbot son:

  • Disponibilidad: Dado que un chatbot es una aplicación de software que se puede alojar, significa que no duerme, por lo tanto siempre está disponible a cualquier hora del día. Esto da a una empresa o persona una gran imagen de marca que en cualquier momento del día los clientes pueden obtener apoyo en sus diversas solicitudes.
  • Reducción de costes: Al ser una aplicación que puede desplegarse en múltiples lugares, reduce el coste de mantener un gran número de representantes de atención al cliente.
  • Eficacia: Un solo chatbot puede desplegarse en varios lugares y también atender simultáneamente múltiples solicitudes a la vez.
  • Mejora de la presencia en línea: Algunos chatbots permiten la integración con otras plataformas de mensajería, esto permite una respuesta coherente enviada a través de múltiples plataformas y que conduce a una mejor identidad de marca.

Requisitos previos


Antes de empezar este tutorial, necesitas tener:

  • Node.js instalado en su máquina local (v16 o v18)
  • Conocimientos básicos de Strapi
  • Conocimientos básicos de Next.js
  • Conocimientos básicos de Tailwind CSS

¿Qué es Next Js?


Next.js es un impresionante framework React para construir aplicaciones altamente dinámicas. Viene con pre-renderización, división automática de código entre muchas otras grandes características fuera de la caja.

¿Qué es Tailwind CSS?


Tailwind CSS es un framework CSS para construir rápidamente interfaces de usuario personalizadas. Con Tailwind CSS, escribimos nuestro CSS directamente en nuestras clases HTML. Esto es bastante útil ya que no necesitamos importar una hoja de estilos externa o utilizar una biblioteca separada para los diseños de interfaz de usuario.

Qué es Strapi


Strapi es un CMS headless de código abierto Node.js que nos permite desarrollar APIs y gestionar contenido fácilmente sin la molestia de construir un proyecto desde cero. Permite la personalización y el autoalojamiento a diferencia de los rígidos CMS tradicionales a los que estamos acostumbrados.

Podemos crear APIs más rápidamente y consumir los contenidos a través de APIs utilizando cualquier cliente REST API o GraphQL.a

Armar un Proyecto Strapi


Configurar un nuevo Proyecto Strapi es bastante sencillo, sólo ejecuta este comando:

  npx create-strapi-app chatbot-assistant --quickstart

Cambia chatbot-assistant por el nombre que prefieras para tu proyecto

Nota: Durante la configuración, no usaremos ninguna plantilla Strapi.

Esto instalaría y crearía una aplicación Strapi y configuraría el proyecto localmente.

Después de la instalación, el navegador abriría una página en localhost:1337 que pediría configurar una cuenta de superadministrador para proceder con Strapi.

Creación de la colección Interchange


A continuación, crearemos un nuevo tipo de colección que almacenará los detalles de cada pregunta y sus respectivas respuestas.

Por lo tanto, cree un tipo de colección llamado interchange que tenga estos campos: question, answer

Al hacer clic en "Continuar" aparecerá otra pantalla para seleccionar los campos de esta colección. Elije el campo Texto de la lista y escribe Pregunta como nombre.

A continuación, seleccionamos el tipo de Texto Largo en la Configuración Base, esto nos permitiría introducir preguntas más largas y descriptivas a la hora de crear un intercambio.

A continuación, pasamos a la pestaña "Configuración avanzada" y marcamos la casilla "Campo obligatorio" para asegurarnos de que este campo es obligatorio al crear un nuevo intercambio. Además, marcamos la casilla "Campo único" para evitar que nuestro intercambio tenga la misma pregunta.

Hacemos clic en Añadir otro campo para añadir el campo de respuesta. A continuación se muestra una tabla con las propiedades de ambos campos en esta colección:

Sembrar Strapi


A continuación procedemos a definir las preguntas y sus respectivas respuestas dadas por nuestro bot.

Para añadir datos a la colección, seleccionamos la colección Intercambios en la barra lateral izquierda, hacemos clic en "Añadir nuevos intercambios" y rellenamos los datos.

Para este tutorial, yo estaría sembrando el intercambio con un intercambio acerca de mí en mente, por lo que nuestro bot puede actuar como un asistente que le dice a los visitantes más sobre nosotros y nuestros servicios. Después de la siembra nuestra colección se ve así:

Permitir el acceso público


Por defecto, cada vez que se crea una API, Strapi crea seis endpoints a partir del nombre dado a la API. Los endpoints generados para Interchange deberían tener este aspecto:

Por defecto, todos ellos van a estar restringidos al acceso público. Necesitamos decirle a Strapi que usted está de acuerdo con exponer estos puntos finales verificados al público.

Ve a Configuración > Plugin de Usuarios y Permisos > Roles y haga clic para editar el Rol Público. A continuación, desplácese hacia abajo a permisos y marque encontrar para Intercambio.

Este endpoint: http://localhost:1337/interchanges  debería estar ahora disponible. Y la respuesta de ejemplo esta:

    [{"id":2,"question":"What are your skills?","answer":"I am skilled at frontend development as well as backend development.","published_at":"2021-11-10T22:04:01.379Z","created_at":"2021-11-10T22:00:18.983Z","updated_at":"2021-11-10T22:04:01.445Z"},
    {"id":3,"question":"How can I reach you?","answer":"You can reach me via my phone line: 0900000000 or via my twitter handle: interchange_demo.","published_at":"2021-11-10T22:04:09.033Z","created_at":"2021-11-10T22:01:07.886Z","updated_at":"2021-11-10T22:04:09.039Z"},
    {"id":4,"question":"How long have you been a developer?","answer":"6 years.","published_at":"2021-11-10T22:04:15.757Z","created_at":"2021-11-10T22:01:50.037Z","updated_at":"2021-11-10T22:04:15.765Z"},
    {"id":5,"question":"Do you have leadership experience?","answer":"Yes, I do.","published_at":"2021-11-10T22:04:21.346Z","created_at":"2021-11-10T22:02:23.115Z","updated_at":"2021-11-10T22:04:21.354Z"},
    {"id":6,"question":"What other skills do you have apart from software development?\n","answer":"I am a technical writer and also a community builder.","published_at":"2021-11-10T22:04:26.091Z","created_at":"2021-11-10T22:03:21.103Z","updated_at":"2021-11-10T22:04:26.102Z"}]

Scaffolding de un proyecto NextJs

Crear una aplicación Next.js

Para crear una aplicación Next.js, abre tu terminal, entra en el directorio en el que deseas crear la aplicación y ejecuta el siguiente comando:

    npx create-next-app -e with-tailwindcss nextjs-chatbot


Esto también configuraría Tailwind CSS con el proyecto

Ejecutar el servidor de desarrollo Next.js

A continuación entramos en el directorio recién creado, en nuestro caso nextjs-chatbot

    cd nextjs-chatbot

Después ponemos en marcha el servidor de desarrollo, ejecutando este comando:

    npm run dev

Si todo se ha configurado correctamente, el servidor next.js debería estar ejecutándose en http://localhost:3000  y deberíamos ver esto en nuestro navegador:

Construyendo Componentes NextJs


A continuación, vamos a cualquier editor de texto de nuestra elección para desarrollar el resto de la aplicación. Nosotros utilizamos Visual Studio Code para este tutorial. Al abrir el proyecto instalado, deberíamos tener una estructura de carpetas como la siguiente:

Para comenzar el diseño de la interfaz, eliminaríamos todo el contenido del archivo index.js que se encuentra dentro de la carpeta pages, este es el punto de entrada del proyecto NextJs. Lo sustituimos por el contenido que aparece a continuación:

    import Head from 'next/head'
    import { useState, useEffect } from 'react'
    import { createMarkup, tranformInterchanges, showBotTyping, getBotAnswer, fetchQuery } from '../utils/helper'
    export default function Home( { interchanges }) {
      const [userQuestion, setUserQuestion] = useState('')
      const [allow, setAllow] = useState(false)
      const [interchange, setInterchange] = useState([])
     
    useEffect(async () => {
     await showBotTyping(setInterchange, [], setAllow)
     setInterchange([{
      owner: false,
      text: tranformInterchanges(interchanges, true)
    }])
    }, [interchanges])
    
    const handleSubmit = async (e) => {
      e.preventDefault()
      if(!userQuestion || !allow) return
      const uQ = userQuestion
      const newInterchange = [...interchange, {
        owner: true,
        text: userQuestion
      }]
      setInterchange(newInterchange)
      setUserQuestion('')
      setAllow(false)
      getBotAnswer(interchanges, setInterchange,  uQ, newInterchange, setAllow)
    }
      return (
        <div className="flex flex-col font-mono items-center justify-center min-h-screen">
          <Head>
            <title>ChatBot Assistant</title>
            <link rel="icon" href="/favicon.ico" />
          </Head>
          <form className="flex flex-col w-full flex-1" onSubmit={handleSubmit}>
           
            <header className="flex w-full h-24 fixed bg-black border-b">
            
              <span className="flex items-center text-white font-bold text-lg p-2"> Bot Assistant</span>
           </header>
            <div className="flex flex-col mt-24 bg-gray-200  overflow-scroll p-2 w-full" style={{ height: "80vh"}}>
            {interchange.map((chat,i) => (
              chat.owner ? 
              <div key={i} className = "user flex flex-row my-2 w-full p-2">
              <span className = "w-2/3"></span>
              <span className = "w-1/3 bg-gray-100 p-2 rounded">
               {chat.text}
              </span>
            </div>
             :   
              <div key={i} className = "bot my-2 bg-gray-100 w-1/2 lg:w-1/3  p-2 rounded">
                <span dangerouslySetInnerHTML={createMarkup(chat.text)} />
              </div>
            ))}
            <div id="scrollTo"></div>
            </div>
            <footer className = "flex flex-row justify-between items-center p-1 h-5/6  w-full -bottom-5">
            <div className = "flex flex-row justify-between flex-1 bg-white w-full">
              <input className = " bg-gray-200 w-2/3 p-2 " placeholder="Type a message" value={userQuestion} onChange={ (e) => { setUserQuestion(e.target.value)}}/>
              <button className = " bg-black p-2 ml-2 w-1/3  text-white" type="submit"> Send</button>
            </div>
            </footer>
          </form>
          
        </div>
      )
    }
    
    export async function getStaticProps() {
      const interchanges = await fetchQuery('interchanges')
      return {
        props: {
          interchanges
        }
      }
    }

Explicación del código anterior


El código anterior se utiliza para mostrar la interfaz de usuario para la interfaz de chat, es decir, tanto los mensajes, área de entrada, así como el botón de enviar.

En la sección superior importamos la función helper de un archivo helper.js, estas funciones se utilizarán para hacer la aplicación funcional:

    import Head from 'next/head'
    import { useState, useEffect } from 'react'
    import { createMarkup, tranformInterchanges, showBotTyping, getBotAnswer, fetchQuery } from '../utils/helper'

A continuación, utilizando los hooks useState, creamos múltiples variables que utilizaremos más adelante en la aplicación para lograr diversos propósitos:
La userQuestion se utiliza para realizar un seguimiento de la pregunta actual que está escribiendo el usuario, es decir, el texto en el cuadro de entrada.

El estado allow se utiliza para evitar que un usuario envíe varios mensajes cuando el bot todavía está respondiendo a un mensaje enviado anteriormente.

El estado de intercambio se utiliza para almacenar internamente los mensajes entre el bot y el usuario.

      const [userQuestion, setUserQuestion] = useState('')
      const [allow, setAllow] = useState(false)
      const [interchange, setInterchange] = useState([])

La porción de código en el useEffect se dispara una vez que se inicia la aplicación y hace lo siguiente:
En primer lugar, muestra una animación del bot tecleando durante unos segundos.

A continuación, establece el primer mensaje por defecto enviado por el bot al usuario, este mensaje contiene la pregunta obtenida de la API Strapi cuando se inició la aplicación.

    useEffect(async () => {
     await showBotTyping(setInterchange, [], setAllow)
     setInterchange([{
      owner: false,
      text: tranformInterchanges(interchanges, true)
    }])
    }, [interchanges])

La función handleSubmit es el manejador que se llama una vez que el usuario envía su mensaje al bot.

Sólo permitimos un envío con éxito si el usuario ha introducido un valor en el cuadro de texto y también sólo si el bot no tiene una pregunta que esté procesando en ese momento.

A continuación, añadimos la nueva pregunta del usuario al estado de intercambio, eliminamos el texto escrito por el usuario del cuadro de entrada y establecemos el estado de permiso en false, para evitar que el usuario envíe otro texto hasta que el bot vuelva con un resultado.

La función de ayuda getBotAnswer se utiliza entonces para obtener la respuesta del bot y actualizar la interfaz de usuario.

    const handleSubmit = async (e) => {
      e.preventDefault()
      if(!userQuestion || !allow) return
      const uQ = userQuestion
      const newInterchange = [...interchange, {
        owner: true,
        text: userQuestion
      }]
      setInterchange(newInterchange)
      setUserQuestion('')
      setAllow(false)
      getBotAnswer(interchanges, setInterchange,  uQ, newInterchange, setAllow)
    }

Como se puede ver en el archivo index.js, hemos importado un archivo helper.js. Esto significa que necesitamos crear este archivo, para ello creamos una carpeta en la raíz de nuestra aplicación llamada utils y luego creamos un archivo en ella llamado helper.js.

A continuación, copiamos el contenido del siguiente archivo en el archivo helper.js recién creado:

    const baseUrl = process.env.BASE_URL || 'localhost:1337'
    export const createMarkup = (text) => {
      return {__html: text};
    }
    export const tranformInterchanges = (interchanges, initial = false) => {
      let initialText = initial ? `<b>Welcome to my page, glad to have you here 🥰</b> <br/>
     Tell me what you would like to know: <br/> <br/> `: ''
      
      interchanges.map((e, i) => {
          initialText += `${(i+1)}. ${e.question} <br /> <br />`
      })
      return initialText
    }
    export const searchInterchange = (interchanges, question) => {
      let result = interchanges.find(e => e.question.toLowerCase().includes(question.toLowerCase()))
      if(result) return result.answer
      return `Cant seem to understand your question, please try again 😔<br><br>
        Here are the options again: <br/> <br/>
        ${tranformInterchanges(interchanges)}
      `
    }
    
    export const showBotTyping = async (setInterchange, prevState, setAllow) => {
      scrollDown()
      await new Promise(resolve => setTimeout(resolve, 1000));
      setInterchange([...prevState, {
        owner: false,
        text: 'Bot Assistant is typing.'
      }])
      scrollDown()
      await new Promise(resolve => setTimeout(resolve, 1000));
      setInterchange([...prevState, {
        owner: false,
        text: 'Bot Assistant is typing..'
      }])
      scrollDown()
      await new Promise(resolve => setTimeout(resolve, 1000));
      setInterchange([...prevState, {
        owner: false,
        text: 'Bot Assistant is typing...'
      }])
      scrollDown()
      
      await new Promise(resolve => setTimeout(resolve, 1000));
      setAllow(true)
      scrollDown()
    }
    
    export const getBotAnswer = async (interchanges, setInterchange, question, prevState, setAllow) => {
      await showBotTyping(setInterchange, prevState, setAllow)
      setInterchange([...prevState, {
        owner: false,
        text: searchInterchange(interchanges,question)
      }])
      scrollDown()
    }
    
    const scrollDown = () => {
      document.getElementById('scrollTo').scrollIntoView({behavior: "smooth", block: "start"});
    }
    
    export const fetchQuery = async (path, params = null) => {
      let url
      if (params !== null) {
        url = `${baseUrl}/${path}/${params}`
      } else {
        url = `${baseUrl}/${path}`
      }
      const response = await fetch(`http://${url}`)
      const data = await response.json()
      return data
    }

Explicación del código anterior


El código anterior contiene varias funciones de ayuda que se utilizan en la aplicación.

Primero, establecemos la URL base para la API, que en nuestro caso es localhost:1337 pero si eventualmente alojamos la API Strapi, entonces actualizaríamos la BASE_URL en el archivo .env a la API Strapi remota.

A continuación, usamos createMarkup para mostrar los mensajes del bot con cualquier formato HTML con el que venga.

    const baseUrl = process.env.BASE_URL || 'localhost:1337'
    export const createMarkup = (text) => {
      return {__html: text};
    }

La función tranformInterchanges se utiliza para mostrar el primer mensaje enviado por el bot al usuario, que contiene todas las posibles preguntas que se pueden formular con un formato fino:

    export const tranformInterchanges = (interchanges, initial = false) => {
      let initialText = initial ? `<b>Welcome to my page, glad to have you here 🥰</b> <br/>
     Tell me what you would like to know: <br/> <br/> `: ''
      
      interchanges.map((e, i) => {
          initialText += `${(i+1)}. ${e.question} <br /> <br />`
      })
      return initialText
    }

El searchInterchange es el corazón de la aplicación, es donde se escanean todas las preguntas del usuario para ver si hay una respuesta adecuada para ella. Si la hay, devuelve una respuesta a partir de las respuestas proporcionadas, si no, devuelve una respuesta indicando que no se han encontrado resultados mientras y mostrando también todas las preguntas que el usuario puede hacer.

    export const searchInterchange = (interchanges, question) => {
      let result = interchanges.find(e => e.question.toLowerCase().includes(question.toLowerCase()))
      if(result) return result.answer
      return `Cant seem to understand your question, please try again 😔<br><br>
        Here are the options again: <br/> <br/>
        ${tranformInterchanges(interchanges)}
      `
    }
    
    export const showBotTyping = async (setInterchange, prevState, setAllow) => {
      scrollDown()
      await new Promise(resolve => setTimeout(resolve, 1000));
      setInterchange([...prevState, {
        owner: false,
        text: 'Bot Assistant is typing.'
      }])
      scrollDown()
      await new Promise(resolve => setTimeout(resolve, 1000));
      setInterchange([...prevState, {
        owner: false,
        text: 'Bot Assistant is typing..'
      }])
      scrollDown()
      await new Promise(resolve => setTimeout(resolve, 1000));
      setInterchange([...prevState, {
        owner: false,
        text: 'Bot Assistant is typing...'
      }])
      scrollDown()
      
      await new Promise(resolve => setTimeout(resolve, 1000));
      setAllow(true)
      scrollDown()
    }

El showBotTyping se utiliza para imitar a un humano, da al bot una sensación humana retrasando su respuesta un poco y utilizando ese tiempo para mostrar un mensaje que el bot está escribiendo. Esta animación de escritura se eliminará del historial de chat una vez que el bot responda.

    export const showBotTyping = async (setInterchange, prevState, setAllow) => {
      scrollDown()
      await new Promise(resolve => setTimeout(resolve, 1000));
      setInterchange([...prevState, {
        owner: false,
        text: 'Bot Assistant is typing.'
      }])
      scrollDown()
      await new Promise(resolve => setTimeout(resolve, 1000));
      setInterchange([...prevState, {
        owner: false,
        text: 'Bot Assistant is typing..'
      }])
      scrollDown()
      await new Promise(resolve => setTimeout(resolve, 1000));
      setInterchange([...prevState, {
        owner: false,
        text: 'Bot Assistant is typing...'
      }])
      scrollDown()
      
      await new Promise(resolve => setTimeout(resolve, 1000));
      setAllow(true)
      scrollDown()
    }

La función getBotAnswer envía la pregunta del usuario al bot y luego actualiza el chat con la respuesta del bot.

    export const getBotAnswer = async (interchanges, setInterchange, question, prevState, setAllow) => {
      await showBotTyping(setInterchange, prevState, setAllow)
      setInterchange([...prevState, {
        owner: false,
        text: searchInterchange(interchanges,question)
      }])
      scrollDown()
    }
    
    const scrollDown = () => {
      document.getElementById('scrollTo').scrollIntoView({behavior: "smooth", block: "start"});
    }

Utilizamos la función scrollDown para mostrar el mensaje actual enviado por el bot o por el usuario. De este modo, se asemeja más a una aplicación de chat y los usuarios no tienen que desplazarse manualmente hacia abajo para ver los mensajes recientes.

    const scrollDown = () => {
      document.getElementById('scrollTo').scrollIntoView({behavior: "smooth", block: "start"});
    }

Y eso es todo para la sección de código de la parte frontend de este tutorial. En la siguiente sección, vamos a ver una demostración de la aplicación terminada.

Conclusión


No hay duda de que el beneficio que aporta un asistente chatbot supera cualquier efecto negativo que pudiera tener. Este método nos permite liberar nuestro tiempo al permitir que este bot responda a preguntas repetitivas sobre nosotros, nuestro negocio, nuestra organización o evento. Las posibilidades de esto son infinitas y sólo se pueden dejar a la imaginación de cada uno.

Este tutorial demostró lo fácil que es construir un bot utilizando tecnologías ya muy comunes.

Fuente

Plataforma de cursos gratis sobre programación

Artículos Relacionados

Mejora tu VSCODE (PRODUCTIVDAD)
· 5 min de lectura
Generando certificados SSL TOTALMENTE GRATIS
· 3 min de lectura