Integrate Website Forms With Reamaze to Provide AI Improved Customer Support and Slack Notifications

At Meant4, we have always prioritized providing exceptional support to our customers. To streamline our support system, we decided to use Reamaze, a robust ticketing and support system. Today we are releasing to the public reamaze-go package under open source licence (MIT). Below you will find a Step-by-Step Example of how you can quickly set up your integration using Google Cloud Run with reamaze-go package, Re:amaze and Slack

Difficulty Level: Advanced

Prerequisite: Access to re:amaze account, access to google cloud console with ability to create Cloud Run service, go programming language, access to slack account.

Takeaway: This article will show you how you can set up simple REST endpoint which will receive data from your webform/application and pass it to re:amaze and notify your team via Slack.

Cloud Run + Re:amaze + Slack

Introduction

Reamaze offers a comprehensive suite of features, including a unified inbox, live chat, automated workflows, and detailed analytics. Reamaze not only helps manage customer interactions but also seamlessly integrates with various platforms, making it a versatile tool for our needs. This makes it an ideal choice for handling support requests and inquiries from various channels (omni channel solution), including our website forms.

To make the integration process smoother, we developed and open-sourced under the MIT License reamaze-go package https://github.com/meant4/reamaze-go. This package allows developers to effortlessly connect their websites/applications and other source of requests to Reamaze channels, enabling automatic ticket creation and support management. We utilized Google Cloud Run to create an simple API endpoint, which use reamze-go to connect webform with our re:amaze account.

In this article, we will guide you through the step-by-step process of integrating your website forms with Re:amaze using the reamaze-go package. By following this guide, you can automate support tickets and notify your team members via Slack whenever a new entry is received in Re:amaze.

Why to add web form data to re:amaze?

Storing web form data in Re:amaze offers several key benefits that enhance both customer service and operational efficiency. Re:amaze provides a centralized platform where all customer interactions, including web form submissions, are automatically logged and organized. This ensures that customer queries are easily accessible to support teams, enabling quicker response times and better follow-up.

Re:amaze integrates seamlessly with various CRM systems, allowing businesses to maintain a cohesive record of customer interactions across multiple channels. The platform's advanced analytics tools also help in tracking and analyzing form data, providing valuable insights into customer behavior and feedback. By utilizing Re:amaze for web form data storage, businesses can improve their customer service workflow, maintain organized records, and gain actionable insights to drive customer satisfaction and retention.

Why to use Google Cloud Run as the solution for hosting REST endpoint?

Using Google Cloud Run for hosting REST endpoints is a strategic choice due to its seamless scalability, cost-effectiveness, and ease of use. Cloud Run allows developers to deploy containerized applications effortlessly, ensuring that your REST API can handle varying levels of traffic without manual intervention. Its serverless nature means you only pay for the compute time your application uses, which can lead to significant cost savings compared to traditional server-based hosting.

Cloud Run offers automatic scaling, robust security features, and integration with other Google Cloud services, simplifying the deployment and management processes. With its support for any programming language and the ability to run stateless containers, Cloud Run provides a flexible and powerful environment for hosting REST endpoints, enabling rapid development and deployment cycles.

Why to use Re:amaze and Slack integration?

Integrating Re:amaze with Slack creates a powerful synergy for customer support and team collaboration. This integration allows customer service teams to receive real-time notifications about customer inquiries directly in Slack, ensuring prompt responses and reducing the need to switch between platforms.

With Re:amaze and Slack working together, support agents can discuss and resolve customer issues more efficiently by leveraging Slack's robust communication tools. By combining the strengths of Re:amaze's customer service capabilities with Slack's collaboration features, businesses can improve response times, foster better teamwork, and ultimately enhance customer satisfaction.

Let's define the process and information flow

For the purpose of this article we have defined the following process in which we are handling web form submission data.
Here's a step-by-step description of the flow:

  1. 1. User Submission: The user fills out a form on the webpage
  2. 2. Send to Cloud Run: The form data is sent to Cloud Run for processin
  3. 3. Process Data: Cloud Run processes the form data to determine its validity
  4. 4. Form Validation Check:
    • Valid: If the form is valid, the data is sent to Re:amaze
    • Invalid: If the form is not valid, the process follows a different path
  5. 5. Invalid Form Handling:
    • The form data is rejected
    • An error message is displayed to the user, prompting them to correct the form
    • The user corrects the form and resubmits it, starting the process over
  6. 6. Valid Form Handling:
    • The valid form data is sent to Re:amaze
    • Re:amaze creates a support ticket using the form data
    • The data is then sent to Slack via Re:amaze Slack integration, notifying the team (support,sales,…)
  7. 7. End: The process ends here, completing the data handling flow
Below we present the above process on the diagram Cloud Run + Re:amaze + Slack

Setting up Google Cloud

To deploy a Cloud Run container using Cloud Build we need to set up Google Cloud Platform (GCP). Follow these steps to set up Google Cloud Project:

Step 1: Create a GCP Project

Create a New Project:
  • Go to the GCP Console: GCP Console
  • Click on the project dropdown at the top and select "New Project"
  • Enter a project name and billing account, then click "Create."

Step 2: Enable Required APIs

Enable APIs:
  • Go to the APIs & Services Dashboard:- APIs & Services
  • Click "Enable APIs and Services"
  • Enable the following APIs:
    • Cloud Build API
    • Cloud Run API
    • Container Registry API (or Artifact Registry API)

Step 3: Set Up Authentication

1. Install Google Cloud SDK:
  • If you haven't already, download and install the Google Cloud SDK from Google Cloud SDK
2. Authenticate with GCP:
  • Open a terminal and run:
    1
    2
    
    gcloud auth login
    gcloud config set project YOUR_PROJECT_ID

Step 4: Prepare Your Application

Create a Dockerfile:
  • In your project directory, create a `Dockerfile` that defines your application environment. Here's our example Dockerfile for REST endpoint app:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
FROM alpine:latest as certs
RUN apk --update add ca-certificates

FROM golang:latest as builder
# Setting up GOPRIVATE
WORKDIR /app
COPY . .
RUN go mod tidy
RUN CGO_ENABLED=0 GOOS=linux go build -o main .

FROM scratch
WORKDIR /app
COPY --from=builder /app/main .
COPY --from=certs /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt

ENTRYPOINT [ "/app/main" ]

Step 5: Create a Cloud Build Configuration File

Create cloudbuild.yaml:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
steps:
- name: 'gcr.io/cloud-builders/docker'
  entrypoint: 'bash'
  args: ['-c','docker build --no-cache -t gcr.io/$PROJECT_ID/${_APP_NAME}:$SHORT_SHA .']
- name: 'gcr.io/cloud-builders/docker'
  args: ['push','gcr.io/$PROJECT_ID/${_APP_NAME}:$SHORT_SHA']
- name: 'gcr.io/cloud-builders/gcloud'
  args:
    - 'beta'
    - 'run'
    - 'deploy'
    - '${_APP_NAME}'
    - '--image=gcr.io/$PROJECT_ID/${_APP_NAME}:$SHORT_SHA'
    - '--set-env-vars=REAMAZE_EMAIL=$_REAMAZE_EMAIL,REAMAZE_BRAND=$_REAMAZE_BRAND,REAMAZE_CATEGORY=$_REAMAZE_CATEGORY,REAMAZE_API_TOKEN=${_REAMAZE_API_TOKEN}'
    - '--region=${_REGION}'
    - '--platform=managed'
    - '--allow-unauthenticated'
substitutions:
  _APP_NAME: "yourendpointservicename"
  _REAMAZE_EMAIL: "dummy@example.com"
  _REAMAZE_API_TOKEN: "reamaze_api_token"
  _REAMAZE_BRAND: "somebrand"
  _REAMAZE_CATEGORY: "reamazecategory"
  _REGION: "europe-west4"

Step 6: Deploy to Cloud Run Using Cloud Build

Submit the Build:
In the terminal, navigate to your project directory and run:
1
  gcloud builds submit --config cloudbuild.yaml .

Step 7: Verify the Deployment

Check the Cloud Run Service:
  • Go to the Cloud Run Console: Cloud Run Console
  • Verify that your service is running and click on the URL to ensure it is working correctly

Optional: Automate Deployments with GitHub

1. Set Up GitHub Repository:
  • Push your project to a GitHub repository.
2. Configure Cloud Build Trigger:
  • Go to Cloud Build Triggers: Cloud Build Triggers
  • Click "Create Trigger"
  • Set up a trigger for your repository to run the build on commits to the main branch

By following these steps, you will have set up GCP to deploy a containerized application to Cloud Run using Cloud Build. This setup ensures your application is built, pushed to a container registry, and deployed to Cloud Run automatically.

Connecting Cloud Run Endpoint with Reamaze

Up until now we were preparing our environment to be able to send REST request to Cloud Run endpoint which will unmarshall request's payload and send it Reamaze. Before you try our sample server you need to get couple of things from your Reamaze account:

1
2
3
4
REAMAZE_EMAIL="dummy@example.com"
REAMAZE_API_TOKEN="yourtokenhere"
REAMAZE_BRAND= "breandname"
REAMAZE_CATEGORY= "reamazecategory"

To get your API_TOKEN https://BRAND.reamaze.com/admin/settings/api_token where BRAND is your brand name.

Once you have all REAMZE data you can set them up in your cloud build trigger (see our cloudbuild.yaml file above) or add them to dev.env file.

dev.env
1
2
3
4
REAMAZE_EMAIL="dummy@example.com"
REAMAZE_API_TOKEN="yourtokenhere"
REAMAZE_BRAND= "breandname"
REAMAZE_CATEGORY= "reamazecategory"

Below you can see our example HTTP server which is ready to deploy to Cloud Run

main.go
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
package main

import (
	"encoding/json"
	"fmt"
	"io"
	"log"
	"net/http"
	"strings"
	"time"

	"github.com/julienschmidt/httprouter"
	"github.com/meant4/reamaze-go/reamaze"
	"github.com/rs/cors"
	"github.com/spf13/viper"
)

var (
	c *viper.Viper
)

type SendMessageBody struct {
	FirstName   string `json:"firstName" validate:"true"`
	LastName    string `json:"lastName" validate:"true"`
	Email       string `json:"email" validate:"true"`
	PhoneNumber string `json:"phoneNumber"`
	CompanyName string `json:"companyName"`
	HearAboutUs string `json:"hearAboutUs" validate:"true"`
	TellUs      string `json:"tellUs" validate:"true"`
	Nda         bool   `json:"nda"`
	Marketing   bool   `json:"marketing"`
}

type ResponseMsg struct {
	ErrCode int      `json:"errCode,omitempty"`
	ErrMsg  string   `json:"errMsg,omitempty"`
	Fields  []string `json:"fields,omitempty"`
	Msg     string   `json:"msg,omitempty"`
	Id      string   `json:"id,omitempty"`
}

const (
	MissingRequired = iota + 100
	InvalidJSON
	WebserviceError
	ReamazeError
)

func init() {
	fmt.Printf("Initializing api %s\n", time.Now().String())
	c = viper.New()
	c.AddConfigPath(".")
	c.SetConfigName("dev")
	c.SetConfigType("env")
	if err := c.ReadInConfig(); err != nil {
		log.Println("Error reading env file", err)
	}
	c.AutomaticEnv()
	// Setting up reamaze variables
	c.SetDefault("REAMAZE_EMAIL", "test@example.com")
	c.SetDefault("REAMAZE_API_TOKEN", "dummy")
	c.SetDefault("REAMAZE_BRAND", "example")
	c.SetDefault("REAMAZE_CATEGORY", "relations")
	c.WatchConfig()
	fmt.Printf("Initialized %d variables: %s\n", len(c.AllKeys()), strings.ToUpper(strings.Join(c.AllKeys(), ", ")))
}

func main() {
	// Initializing router
	router := httprouter.New()
	router.POST("/v1/sendmessage", SendReamazeMessage)
	// Setting default CORS headers
	handler := cors.Default().Handler(router)
	log.Fatal(http.ListenAndServe(":8080", handler))
}

func SendReamazeMessage(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
	var incomingMsg SendMessageBody
	w.Header().Add("Content-Type", "application/json")

	body, err := io.ReadAll(r.Body)
	if err != nil {
		fmt.Fprintf(w, "%s", err)
	}
	defer r.Body.Close()
	if len(body) > 0 {
		err := json.Unmarshal(body, &incomingMsg)
		if err != nil {
			respMsg := ResponseMsg{
				ErrCode: InvalidJSON,
				ErrMsg:  fmt.Sprintf("Invalid JSON request. %s", err),
				Msg:     fmt.Sprintf("Invalid JSON request. %s", err),
			}
			resp, _ := json.Marshal(respMsg)
			w.WriteHeader(http.StatusBadRequest)
			fmt.Fprint(w, string(resp))
			return
		}

		// Initializing new reamaze client
		reamazeClient, err := reamaze.NewClient(c.GetString("REAMAZE_EMAIL"), c.GetString("REAMAZE_API_TOKEN"), c.GetString("REAMAZE_BRAND"))
		if err != nil {
			log.Println(err)
		}

		// Preparing reamaze payload to create new conversation
		payload := &reamaze.CreateConversationRequest{}
		payload.Conversation.Category = c.GetString("REAMAZE_CATEGORY")
		payload.Conversation.Message.Body = incomingMsg.TellUs
		payload.Conversation.User.Email = incomingMsg.Email
		payload.Conversation.User.Name = incomingMsg.FirstName + " " + incomingMsg.LastName
		payload.Conversation.Data = struct {
			Phone       string `json:"phone,omitempty"`
			CompanyName string `json:"company_name,omitempty"`
			HearAboutUs string `json:"hear_about_us,omitempty"`
			Nda         bool   `json:"nda"`
			Marketing   bool   `json:"marketing_approval"`
			FirstName   string `json:"first_name,omitempty"`
			LastName    string `json:"last_name,omitempty"`
		}{
			Phone:       incomingMsg.PhoneNumber,
			CompanyName: incomingMsg.CompanyName,
			HearAboutUs: incomingMsg.HearAboutUs,
			Nda:         incomingMsg.Nda,
			Marketing:   incomingMsg.Marketing,
			FirstName:   incomingMsg.FirstName,
			LastName:    incomingMsg.LastName,
		}
		payload.Conversation.User.Data = struct {
			Phone       string `json:"phone,omitempty"`
			CompanyName string `json:"company_name,omitempty"`
			Nda         bool   `json:"nda"`
			Marketing   bool   `json:"marketing_approval"`
			FirstName   string `json:"first_name,omitempty"`
			LastName    string `json:"last_name,omitempty"`
		}{
			Phone:       incomingMsg.PhoneNumber,
			CompanyName: incomingMsg.CompanyName,
			Nda:         incomingMsg.Nda,
			Marketing:   incomingMsg.Marketing,
			FirstName:   incomingMsg.FirstName,
			LastName:    incomingMsg.LastName,
		}

		_, err = reamazeClient.CreateConversation(payload)
		if err != nil {
			log.Println("error from CreateConversation:", err)
			respMsg := ResponseMsg{
				ErrCode: ReamazeError,
				ErrMsg:  fmt.Sprintf("Internal communication error: %s", err),
				Msg:     fmt.Sprintf("Internal communication error: %s", err),
			}

			resp, _ := json.Marshal(respMsg)
			w.WriteHeader(http.StatusServiceUnavailable)
			fmt.Fprint(w, string(resp))
			return
		}

		respMsg := ResponseMsg{
			Msg: "OK",
		}
		resp, _ := json.Marshal(respMsg)
		w.WriteHeader(http.StatusOK)
		fmt.Fprint(w, string(resp))
		return
	}
}

You can find full example in reamaze-go repository in /examples/cloudrun folder https://github.com/meant4/reamaze-go.

To test your integration you can send POST request to /v1/sendmessage endpoint with empty payload and you should receive "Invalid JSON request." This means your endpouint is up and running.In our example the correct payload has a following form:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
{
    "firstName": "test",
    "lastName": "test",
    "email": "tests@example.com",
    "phoneNumber": "298345723",
    "companyName": "None",
    "hearAboutUs": "google",
    "tellUs": "Hi I would like to know more about your reamaze-go package ",
    "marketing": true,
    "nda": false
}

The above example is our contact's form json data, we have skipped data validation part for clarity purposes.

Reamaze AI enhanced response and sentiment analysis

All messages being send to /v1/sendmessage endpoint are now being stored and handled by Reamaze. This means that beside standard features like search, filtering, assigment to proper department etc. we have some nice new features like "Improve My Response" with AI and Sentiment Analysis of the message. Below we are presenting the look of our previous section json data in Reamaze with red boxes around AI tools we have mentioned:

Sample json data presented in Reamaze

By providing simple response

1
"Hi Test, we can tell you more let's have a call and discuss"

and hitting "Improve My Response" we are ending up with

1
2
"Hi Test, 
we would be happy to provide you with more information about our reamaze-go package. Let's schedule a call to discuss all the details and answer any questions you may have. Please let us know a convenient time for you, and we will arrange a call at your earliest convenience."

Going further, by clicking on "Sentiment Analysis" we receive info "Customer is showing interest in a specific product but did not express any strong positive or negative emotions."
See the picture below:

Sample json data presented in Reamaze

Reamaze and Slack

By using the `reamaze-go` package, a web form can be seamlessly integrated with Reamaze, allowing it to be embedded within the current company communication process, such as Slack. In this example, we have successfully integrated Reamaze with Slack. As a result, each message submitted via the web form is directed to Reamaze, where it is managed and tracked. Additionally, we receive real-time notifications in Slack, ensuring prompt attention and response to all incoming messages. This integration enhances our communication efficiency and ensures that no customer query is missed.

Sample json data presented in Reamaze

Summary

In this example, we've demonstrated how to integrate Reamaze with Slack. Each message sent via the web form is automatically routed to Reamaze, where it is managed and tracked. At the same time, real-time notifications are sent to Slack, ensuring that our team never misses a customer query and can respond promptly.

This is just a short example of the reamaze-go integration application, showcasing the potential to enhance your support responses with AI. But this is only the beginning! The possibilities are endless, and we are excited to help you explore them.

If you're interested in modeling a more complex process or want to learn more about how this integration can benefit your business, we'd love to hear from you. Click here to contact us and take your customer support to the next level!

Written by:

 avatar

Maciej Perliński

System Architect / Senior Golang

Read more like this: