Blog Zenvia

O melhor portal de Marketing e Vendas para a sua empresa

Saiba como desenvolver uma ferramenta para divulgar seus produtos

Aprenda a desenvolver uma ferramenta de divulgação de produtos com o Zenvia Flow, capaz de criar chatbots, integrar softwares e muito mais com APIs.

A chegada repentina da pandemia do COVID-19 pegou todos os setores de surpresa. Muitos não souberam como administrar seu negócio e por consequência tiveram suas portas fechadas.  

As organizações que conseguiram manter o fluxo de trabalho mesmo com o sistema remoto, contaram com o apoio da tecnologia para efetivar seus serviços, as empresas marcaram reuniões online, utilizaram o WhatsApp e e-mails para se comunicaram.  

Um dos poucos saldos positivos durante o ano de 2020 foi o crescimento exponencial do e-commerce. De acordo com uma pesquisa realizada pela Câmara Brasileira da Economia Digital e da Neotrust, o comércio digital faturou 122% em relação ao ano de 2019 até o mês de novembro.  

A alta no comércio digital é um grande resultado para as empresas varejistas, entretanto, o e-commerce ainda representa somente 8,6% do setor de acordo com uma pesquisa realizada em outubro.  

Estes números baixos podem ser justificados por alguns pontos como o receio dos clientes em compartilhar dados financeiros, dificuldade em mexer no site e valores altos como frete de produtos.  

Muitos clientes vão em busca do serviço de e-commerce prezando bons valores e descontos relevantes para efetivar a compra. A melhor forma de utilizar a tecnologia ao seu favor, é contar com ferramentas versáteis que possam facilitar o seu trabalho. 

Zenvia flow é uma ferramenta capaz de criar chatbots, configurar URAs, programar réguas de comunicação, integrar softwares e canais de comunicação por meio de APIs.  

Com o Flow, é possível desenvolver fluxos próprios de serviços, ou utilizar as criações disponíveis da Zenvia. Uma das ferramentas ofertadas é a de “Divulgação de Serviços e Produtos”, com este suporte é possível criar um vendedor virtual que irá promover seus produtos e engajar seus clientes.  

Aqui você encontrará:

1. Criando e preparando o fluxo Zenvia
2. Criando a aplicação Node.js
3. Criando o banco de dados SQLite
4. Criando o Webhook
5. Configurando o envio das promoções

Além disso, a ferramenta mostrará para seus usuários as promoções que estão ativas no seu e-commerce. Com esta funcionalidade, é possível modernizar seu varejo online e entregar ao cliente um serviço moderno que o auxilia.  

A criação desta ferramenta é bem simples. Acompanhe no tutorial abaixo como realizá-la e aplique no seu e-commerce o suporte. 

A aplicação desenvolvida neste tutorial está disponível no nosso repositório do GitHub.

Criando e preparando o fluxo Zenvia

Primeiro, é preciso ter uma conta criada na Zenvia, para isto basta entrar no site app.zenvia.com, clicar em “CRIAR UMA CONTA” no canto superior direito e preencher os campo

Para criar o seu fluxo, vá para o Menu Principal > Produtos > Zenvia Flow > Novo Fluxo > Divulgação de Produtos e Serviços > Criar agora > Web Chat > Criar Novo

Acabamos de criar um fluxo baseado em um preset da Zenvia de divulgação de produtos e serviços. Por padrão, este fluxo mostra ao usuário uma lista de categorias de produtos de uma loja de roupas que estão em promoção e espera a resposta do usuário para mostrar alguns produtos “mockados” no exemplo. O que vamos fazer neste tutorial é tornar este fluxo dinâmico, buscando a lista de promoções em uma base de dados através de uma API Rest. Vamos começar a alterar o fluxo para se adequar ao nosso caso de uso.

1- No card Mensagem inicial remova a opção de resposta Outras opções:

2- Adicione um nó ao fluxo logo entre a tomada de decisão que valida a mensagem retornada pelo usuário e o carrossel de calças e configure a Json API:

Logo mais vamos gerar este URL a ser colocado, então lembre-se desta tela pois voltaremos aqui para colocá-lo.

O que acabamos de fazer foi alterar o fluxo da conversa, onde caso o usuário responder Calças será enviada uma requisição GET ao URL que ainda vamos gerar enviando um query param chamado categoria com o valor calças.

3- Remova o card de Outras opções:

Criando a aplicação Node.js

1- Instale o Node.js no seu computador (de preferência a versão LTS);

1.1- opcional – Instale o yarn. O Node.js possui um gerenciador de pacotes padrão chamado npm (Node Package Manager), porém existe um gerenciador diferente chamado yarn. No restante deste artigo, haverão as opções de instalação para ambos gerenciadores de pacote como no passo a seguir.

2- Inicie o projeto criando o package.json com o seguinte comando no terminal:

npm init -y
yarn init -y

3- Instale o ts-nodets-node-dev e o typescript como dependências de desenvolvimento:

npm i ts-node ts-node-dev typescript -D
yarn add ts-node ts-node-dev typescript -D

3.1 – Instale o arquivo de configuração do typescript:

npx typescript --init

4- Abra o arquivo package.json e insira o script para iniciar o servidor assim como na área grifada em cinza:

{
  "name": "zenvia-flow",
  "version": "1.0.0",
  "main": "index.js",
  "license": "MIT",
  "scripts": {
    "dev": "ts-node-dev --transpile-only --ignore-watch node_modules --respawn src/index.ts"
  },
  "devDependencies": {
    "ts-node": "^9.1.1",
    "ts-node-d": "^1.1.1",
    "typescript": "^4.1.3"
  }
}

4.1- Sempre que você quiser executar a aplicação basta executar no terminal:

npm run dev
yarn dev

Criando o banco de dados SQLite

SQLite é uma biblioteca em linguagem C que implementa um banco de dados SQL embutido. Este tipo de banco de dados é indicado para ambiente de testes, pois ele inteiro fica salvo em um único arquivo sendo fácil de transportá-lo, porém não possui um nível de complexidade e segurança recomendado para um ambiente de produção. Para fins didáticos, o SQLite é uma opção perfeita já que não precisa de instalação local para que ele funcione.

Para manusear o banco de dados, vamos utilizar o Prisma, um ORM (Object-Relational-Mapper) que irá facilitar o manuseio das informações no banco, permitindo consultas e alterações sem a necessidade do conhecimento de consultas SQL. Outro motivo muito bom para o uso do Prisma é a facilidade para alterar a escolha do banco de dados, onde basta apenas mudar a configuração dele em um arquivo, excluindo a necessidade de alterar as consultas, já que não fazemos as consultas SQL diretamente.

1- Instale o prisma para criarmos e manusearmos nosso banco de dados:

npm i @prisma/client @prisma/cli
yarn add @prisma/client @prisma/cli

2- Crie o arquivo prisma/schema.prisma:

datasource db {
  provider = "sqlite"
  url      = "file:./dev.db"
}
generator client {
  provider = "prisma-client-js"
}
model Categoria {
  id           Int        @id @default(autoincrement())
  nome         String     @unique
}
model Produto {
  id           Int        @id @default(autoincrement())
  nome         String
  categoria    Categoria  @relation(fields: [categoriaId], references: [id])
  categoriaId  Int
  valor        Float
}
model Promocao {
  id           Int        @id @default(autoincrement())
  produto      Produto    @relation(fields: [produtoId], references: [id])
  produtoId    Int
  valor        Float
}


3-
 Crie o banco de dados SQLite baseado no schema.prisma com o comando:

npx prisma migrate dev --name init --preview-feature

4- Crie o arquivo prisma/seed.ts, ele servirá para preencher o banco de dados com alguns produtos e promoções a serem exibidos posteriormente no chat do flow:

import { PrismaClient } from '@prisma/client'
const prisma = new PrismaClient()
const main = async () => {
  // Inserção das categorias
  await prisma.categoria.create({ data: { id: 1, nome: 'calças' }})
  await prisma.categoria.create({ data: { id: 2, nome: 'camisas' }})
  await prisma.categoria.create({ data: { id: 3, nome: 'sapatos' }})
  console.log('Categorias criadas.')
  
  // Inserção dos produtos
  await prisma.produto.create({data: { id: 1, nome: 'Calça Modelo 1', categoriaId: 1, valor: 39.99 }})
  await prisma.produto.create({data: { id: 2, nome: 'Calça Modelo 2', categoriaId: 1, valor: 29.99 }})
  await prisma.produto.create({data: { id: 3, nome: 'Calça Modelo 3', categoriaId: 1, valor: 47.99 }})
  await prisma.produto.create({data: { id: 4, nome: 'Calça Modelo 4', categoriaId: 1, valor: 68.89 }})
  await prisma.produto.create({data: { id: 5, nome: 'Camisa Modelo 1', categoriaId: 2, valor: 39.99 }})
  await prisma.produto.create({data: { id: 6, nome: 'Camisa Modelo 2', categoriaId: 2, valor: 29.99 }})
  await prisma.produto.create({data: { id: 7, nome: 'Camisa Modelo 3', categoriaId: 2, valor: 47.99 }})
  await prisma.produto.create({data: { id: 8, nome: 'Camisa Modelo 4', categoriaId: 2, valor: 68.89 }})
  await prisma.produto.create({data: { id: 9, nome: 'Sapato Modelo 1', categoriaId: 3, valor: 85.99 }})
  await prisma.produto.create({data: { id: 10, nome: 'Sapato Modelo 2', categoriaId: 3, valor: 95.29  }})
  await prisma.produto.create({data: { id: 11, nome: 'Sapato Modelo 3', categoriaId: 3, valor: 157.79 }})
  await prisma.produto.create({data: { id: 12, nome: 'Sapato Modelo 4', categoriaId: 3, valor: 240.99 }})
  console.log('Produtos criados.')
  
  // Inserção das promoções
  await prisma.promocao.create({data:{ id: 1, produtoId: 1, valor: 29.99 }})
  await prisma.promocao.create({data:{ id: 2, produtoId: 2, valor: 18.78 }})
  await prisma.promocao.create({data:{ id: 3, produtoId: 4, valor: 48.89 }})
  await prisma.promocao.create({data:{ id: 4, produtoId: 5, valor: 31.19 }})
  await prisma.promocao.create({data:{ id: 5, produtoId: 8, valor: 47.49 }})
  await prisma.promocao.create({data:{ id: 6, produtoId: 11,  valor: 121.44 }})
  await prisma.promocao.create({data:{ id: 7, produtoId: 12,  valor: 198.8 }})
  console.log('Promoções criadas.')
}
 
main().catch((e) => console.error(e))

5- Adicione o script seed no arquivo package.json

{
  "name": "zenvia-flow",
  "version": "1.0.0",
  "main": "index.js",
  "license": "MIT",
  "scripts": {
    "dev": "ts-node-dev --transpile-only --ignore-watch node_modules --respawn src/index.ts",
    "seed": "ts-node prisma/seed.ts"
  },
  "devDependencies": {
    "ts-node": "^9.1.1",
    "ts-node-d": "^1.1.1",
    "typescript": "^4.1.3"
  }
}

6- Execute o script seed no arquivo terminal para popular o banco de dados criado anteriormente com as informações presentes no arquivo prisma/seed.ts:

npm run seed
yarn seed

Criando o Webhook

1- Instale o express e o body-parser para criarmos nossa API:

npm i express body-parser && npm i @types/express -D
yarn add express body-parser && yarn add @types/express -D

2- Crie o arquivo src/server.ts:

import express from 'express'
import bodyParser from 'body-parser'
import routes from './routes'
// Inicializa o express e define uma porta
const app = express()
// Indica para o express usar o JSON parsing do body-parser
app.use(bodyParser.json())
// Indica para o express usar o as rotas do arquivo routes
app.use(routes)
// Indica para o express escutar a porta 3000
app.listen(3000, () => console.log(`Server running on port 3000`))

3- Crie o arquivo de rotas src/routes.ts:

import express from 'express'
import { searchPromotionsController } from './UseCases/SearchPromotions'
const routes = express.Router()
routes.post('/hook', searchPromotionsController.handle))
export default routes

searchPromotionsController será criado mais tarde.

4- Crie o arquivo com a tipagem do repositório que lida com a busca as informações no banco de dados src/repositories/PromocaoRepository.ts:

import { Promocao } from './../entities/Promocao'
 
export interface IPromocaoRepository {
  findByCategory(category: string): Promise<Promocao[]>
}

5- Crie os arquivos Categoria.ts, Produto.ts, Promocao.ts de tipagem das entidades do banco de dados na pasta src/entities respectivamente:

export interface Categoria {
  id: number
  nome: string
}
import { Categoria } from './Categoria'
 
export interface Produto {
  id: number
  nome: string
  categoria: Categoria
  categoriaId: string
  valor: number
}
import { Produto } from './Produto'
 
export interface Promocao {
  id: number
  produto: Produto
  produtoId: number
  valor: number
}

6- Crie o arquivo com o reposítorio que busca as informações src/repositories/implementations:

import { Promocao } from '../../entities/Promocao'
import { PrismaClient } from '@prisma/client'
import { IPromocaoRepository } from '../PromocaoRepository'
 
const prisma = new PrismaClient()
 
export class PromocaoRepositories implements IPromocaoRepository {
  async findByCategory(category: string): Promise<Promocao[]> {
    try {
      const produtos = await prisma.promocao.findMany({
        where: { produto: { categoria: { nome: category } } },
        select: {
          produto: true,
          valor: true,
        },
      })
      // @ts-ignore
      return produtos
    } catch (error) {
      console.log('error', error)
      return []
    }
  }
}

7- Vamos criar o caso de uso SearchPromotions, comece criando o arquivo src/UseCases/SearchPromotionsUseCase.ts:

import { PromocaoRepositories } from '../../repositories/implementations/PromocaoRepository'
 
export class SearchPromotionsUseCase {
  async execute(categoryName: string) {
    try {
      // Inicialização do repositório
      const promocaoRepositories = new PromocaoRepositories()
 
      // Chamada findByCategory do repositório para buscar as promoções de acordo com a categoria
      const promocoes = await promocaoRepositories.findByCategory(categoryName)
 
      // Com as informações retornadas, prepara as informações para serem transformadas na mensagem a ser enviada
      const message = promocoes.map((promocao) => {
        return `\n${
          promocao.produto.nome
        }:\n De R$${promocao.produto.valor
          .toString()
          .replace(/[./s]/g, ',')}\n Por: R$${promocao.valor
          .toString()
          .replace(/[./s]/g, ',')}\n`
      })
 
      // Retorna a mensagem
      return `Estas são as promoções da categoria ${categoryName}:\n${message.join()}\n Pesquise o nome do produto na nossa barra de busca do site para encontrar a página com a promoção.`
    } catch (error) {
      console.log(error)
    }
  }
}
 

8- Crie o arquivo src/UseCases/SearchPromotionsController.ts:

import { Request, Response } from 'express'
import { SearchPromotionsUseCase } from './SearchPromotionsUseCase'
 
export class SearchPromotionsController {
  async handle(request: Request, response: Response): Promise<Response> {
    // Armazena o parâmetro de consulta CATEGORIA em uma variável
    const { categoria } = request.query
 
    // Verificação
    if (!categoria) {
      return response
        .status(400)
        .json({ erro: 'Parâmetro de consulta categoria é obrigatório' })
    }
 
    try {
      // Inicialização da classe SearchPromotionsUseCase
      const searchPromotionsUseCase = new SearchPromotionsUseCase()
 
      // Chamada à função execute para a busca das informações e criação da mensagem
      const message = await searchPromotionsUseCase.execute(categoria.toString())
 
      // Retorno da mensagem
      return response.status(200).json({ mensagem: message })
    } catch (err) {
      // Em caso de erro retorna o status 400 com uma mensagem de erro
      return response.status(400).json({
        message: err.message || 'Unexpected Error.',
      })
    }
  }
}

9- Agora, crie o arquivo src/UseCases/SearchPromotions/index.ts

import { SearchPromotionsController } from './SearchPromotionsController'
 
const searchPromotionsController = new SearchPromotionsController()
 
export { searchPromotionsController }

Pronto! A parte prática da sua aplicação está pronta. Ela é capaz de procurar no banco de dados todos os produtos de uma determinada categoria cadastrada no banco que estejam em promoção. Após buscar as informações ela também formata uma mensagem e retorna ao fluxo pronta para ser enviada.

Agora que a aplicação está pronta, precisamos criar um link para que o fluxo possa enviar a requisição que criamos lá no início deste tutorial. Para isso, vamos utilizar o ngrok para expor nossa porta 3000 (porta em que a aplicação está rodando) e criar um link público para que possa ser enviadas requisições http diretamente para a nossa aplicação local. Se a sua aplicação estivesse hospedada em algum site, não seria a necessidade dessa criação de um link público, pois já haveria um.

Faça login no site, baixe a versão para Windows, extraia o zip, execute a aplicação (abrirá um terminal), autentique-se digitando ngrok authtoken SEU_TOKEN (seu token está na primeira tela do seu dashboard) e exponha a porta da aplicação (3000) digitando ngrok http 3000

Após expor a porta da sua aplicação copie o link que aparecerá no terminal, volte para a última tela apresentada no passo 2 da primeira seção e cole o link copiado do terminal no site. Lembre-se de colocar o URN /hook que é o recurso que disponibilizamos na nossa API (algo semelhante a isso: http://396e5b25cf84.ngrok.io/hook):

Lembre-se que ao fechar o ngrok e expor a porta novamente, será gerado um novo link, então você deve ir ao fluxo e atualizar o link que estiver lá.

Configurando o envio das promoções

De volta ao fluxo, vamos configurá-lo para receber a mensagem da API e repassá ao usuário através do chat.

1– Crie um nó após a chamada à API Json criada anteriormente e configure o envio de uma mensagem ao usuário, enviando a variável #{response.mensage} (variável onde está a mensagem retornada da nossa API.

2- Agora, pode remover o carrossel original do preset:

Pronto! Seu fluxo está pronto para responder sobre as promoções das calças e você pode salvar o fluxo e testá-lo:

3- Nossa aplicação está pronta para pesquisar qualquer uma das categorias cadastradas no banco de dados, agora basta você configurar seu fluxo para enviar a requisição à API para as demais opções, criando um nó de Json API igual o das calças, apenas trocando o valor do parâmetro de consulta para a categoria desejada e, depois da chamada, criar a mensagem. O resultado final deve ficar algo parecido com isso:

4- Com seu fluxo pronto, você pode publicá-lo e incorporá-lo facilmente usando o html disponibilizado ou com alguma das outras opções disponíveis:

Viu que bacana o que dá pra fazer com o Zenvia Flow? Criamos uma aplicação que simula um simples backend de e-commerce de uma forma bem simplificada para fins didádicos, onde há o cadastro de promoções e produtos separados por categorias e que permite a consulta de quais produtos de determinada categoria estão em promoção e retorna uma mensagem com uma lista simples utilizando apenas texto.

Com a nossa aplicação seria possível o cadastro de mais produtos e mais categorias e, depois, seria apenas necessário adicionar ao fluxo mais chamadas à nossa API, apenas alterando o query param (parâmetro de consulta).

Zenvia API's
Escrito por

Zenvia