DigitalCX's ready-to-go integration between DigitalCX and the Google Assistant
npm install @cxco/google-assistantgactions SDK in your system so you can hook up the actions to the project that is running in google.
gactions sdk
gactions sdk executable by running chmod ugo+x gactions
./gactions init, this will create an action.json file that you will use to set up the calls to your project
action.json to be similar to the one underneath
action.json run the command ./gactions update --action_package action.json --project to configure which are the intents that exist and where do they map
can be seen in the Actions on Google project settings
action.json
json
{
"actions": [
{
"description": "Default Welcome Intent",
"name": "MAIN",
"fulfillment": {
"conversationName": "localhost" // You can define here the conversations that fulfill this intent
},
"intent": {
"name": "actions.intent.MAIN",
"trigger": {
"queryPatterns": [
"talk to digitalcx support portal" // Define a pattern that you use to talk to the actions on google project
]
}
}
}
],
"conversations": {
"localhost": { // Define the conversation "server"
"name": "localhost", // Give it a name
"url": "https://example.com/googleassistant" // Your favorite URL
}
},
"locale": "en"
}
`
Installation
`bash
npm i @cxco/google-assistant
`
Configuration
The Google Assistant Integration offers a number of project configuration options, some of them required and some of them optional. All configuration options need to be assigned to a single 'actionsProject' object.
|Parameter Name|Type|Description|Required|Example|
|:-|:-|:-|:-|:-|
|project|object|An object containing the information required to connect and authenticate your application with and to the DigitalCX engine.|yes|{
"customerKey":"ckey",
"projectKey":"pkey",
"culture":"en",
"apiKey":"api key",
"env":"production"
}|
|onLoadEvent|string|A string representing the DigitalCX event you'd like the Google Assistant to trigger and welcome the end user with.|yes|dcx-google-assistant-onload|
|onCancelEvent|string|A string representing the DigitalCX event you'd like the Google Assistant to trigger and end the conversation with.|no|dcx-google-assistant-oncancel|
Basic Usage
`JavaScript
const express = require('express')
const { actionssdk } = require('actions-on-google')
const googleAssistant = require('@cxco/google-assistant')
const bodyParser = require('body-parser')
const app = express()
const actionsApp = actionssdk()
const actionsProject = {
project: {
customerKey: 'customerA',
projectKey: 'projectB',
culture: 'en',
apiKey: 'xxxxxxxx-xxxx-xxxx-xxxxxxxxxxxxxxxx',
env: 'cms'
},
onLoadEvent: 'on_load',
onCancelEvent: 'on_end'
}
const googleAssistantPayload = {
actionsProject,
actionsApp
}
app.use(bodyParser.json())
app.use('/googleassistant', (req, res, next) => {
googleAssistant(googleAssistantPayload)(req, res)
})
app.listen(3000)
`
Hooks
With hooks you can add logic between DigitalCX and Google Assistant.
There are three hooks for every Google Action Intent. You can add custom logic and manipulate the input data inside every hook.
All specified hooks will trigger for every basic intent ('actions.intent.MAIN', 'actions.intent.TEXT', 'actions.intent.CANCEL').
The defined hooks ordered on callstack:
|Hooks|Description|
|:-|:-|
|onAsk|Executes before request to DCX|
|onAnswer|Executes after response from DCX|
|onSSML|Executes after SSML formatting and before request to Google Assistant|
Hook signature
The hooks are methods of the Hooks class derived from the GAI package. To define a hook you initiate a new hooks instance. Then assign a callback function to the method. This curried function uses two arguments, the intentName and the input. The intentName is a string that can be used inside the hook to add logic for a specific intent. The input argument can be modified inside the hook and must be returned! Assign the class to the Google Assistant payload.
`JavaScript
hooks.onAsk = (intentName) => (input) => {
return input
}
`
Example of multiple hooks:
`JavaScript
const express = require('express')
const { actionssdk } = require('actions-on-google')
const googleAssistant = require('@cxco/google-assistant')
const bodyParser = require('body-parser')
const app = express()
const actionsApp = actionssdk()
// Require hooks class
const Hooks = require('@cxco/google-assistant/hooks')
const actionsProject = {
project: {
customerKey: 'customerA',
projectKey: 'projectB',
culture: 'en',
apiKey: 'xxxxxxxx-xxxx-xxxx-xxxxxxxxxxxxxxxx',
env: 'cms'
},
onLoadEvent: 'on_load',
onCancelEvent: 'on_end'
}
// Create new hooks instance
hooks = new Hooks()
/**
* Hook that can modify the DigitalCX request payload per Intent
* @param {String} intentName 'actions.intent.MAIN' || 'actions.intent.TEXT' || 'actions.intent.CANCEL'
* @param {Object} dcxPayload payload for DigitalCX request(@cxco/dcx-connector)
* @return {Object} dcxPayload
*/
hooks.onAsk = intentName => dcxPayload => (
// Return the DigitalCX payload adding custom context
{
metadata: {
dimensions: [{ Integration: 'Test' }]
}
})
/**
* Hook that can modify the response from DigitalCX per Intent
* @param {String} intentName 'actions.intent.MAIN' || 'actions.intent.TEXT' || 'actions.intent.CANCEL'
* @param {Object} dcxResponse normalised response from DigitalCX (@cxco/dcx-connector)
* @return {Object} dcxResponse
*/
hooks.onAnswer = intentName => dcxResponse => {
// Modify the DigitalCX response before parsing it to SSML
dcxResponse.data.answer = ${dcxResponse.data.answer} (DigitalCX answer is modified by the onAnswer hook)
return dcxResponse
}
/**
* Hook that can modify the Google Actions request payload per Intent
* https://www.npmjs.com/package/ssml-builder Formatted SSML response for Google Actions
* @param {String} intentName 'actions.intent.MAIN' || 'actions.intent.TEXT' || 'actions.intent.CANCEL'
* @param {Object} handlerResponse Result from dcxResponseHandler which contains : data, metadata and speech object
* @return {Object} handlerResponse
*/
hooks.onSSML = intentName => handlerResponse => {
// Modify the SSML object on the CANCEL intent / DCX onEnd event.
if (intentName === 'actions.intent.CANCEL') {
handlerResponse.speech.sentence('This added sentence to the SSML object is modified by the onSSML hook')
}
return handlerResponse
}
app.use(bodyParser.json())
app.use('/googleassistant', (req, res, next) => {
googleAssistant({ actionsProject, actionsApp, hooks })(req, res)
})
app.listen(3000)
`
Custom Intents
You can add custom intents and / or overwrite default intents stated in the Google Assistant Integration. This can be done by mapping your custom intents and adding it to the Google Assistant Integration payload.
`JavaScript
const express = require('express')
const { actionssdk } = require('actions-on-google')
const googleAssistant = require('@cxco/google-assistant')
const bodyParser = require('body-parser')
const app = express()
const actionsApp = actionssdk()
const actionsProject = {
project: {
customerKey: 'customerA',
projectKey: 'projectB',
culture: 'en',
apiKey: 'xxxxxxxx-xxxx-xxxx-xxxxxxxxxxxxxxxx',
env: 'cms'
},
onLoadEvent: 'on_load',
onCancelEvent: 'on_end'
}
const customIntents = new Map()
// Overwriting a custom intent
customIntents.set('customIntentName', (conv, input) => {
conv.ask('Hello world!')
})
// Overwriting a default intent
customIntents.set('actions.intent.MAIN', (conv, input) => {
conv.ask('Hello world!')
})
app.use(bodyParser.json())
app.use('/googleassistant', (req, res, next) => {
googleAssistant({ actionsProject, actionsApp, customIntents })(req, res)
})
app.listen(3000)
`
Custom Intents using the dcx-connector
The dcx-connector package can be used to connect to the DCX endpoints and retrieve normalized answers.
The dcxResponseHandler function (included in the GAI) returns data and metadata from the connector and formatted SSML.
Installing the dcx-connector:
`bash
npm i @cxco/dcx-connector
`
Usage:
`Javascript
const express = require('express')
const { actionssdk } = require('actions-on-google')
const googleAssistant = require('@cxco/google-assistant')
const { dcxResponseHandler } = require('@cxco/google-assistant/formatter')
const { doGetRequest } = require('@cxco/dcx-connector')
const bodyParser = require('body-parser')
const app = express()
const actionsApp = actionssdk()
const actionsProject = {
project: {
customerKey: 'customerA',
projectKey: 'projectB',
culture: 'en',
apiKey: 'xxxxxxxx-xxxx-xxxx-xxxxxxxxxxxxxxxx',
env: 'cms'
},
onLoadEvent: 'on_load',
onCancelEvent: 'on_end'
}
const customIntents = new Map()
customIntents.set('customIntentName', async (conv, input) => {
const dcxPayload = {
type: 'ask',
data: {
userInput: input
},
metadata: {
sessionId: conv.user.storage.id,
tDialogState: conv.user.storage.tDialogState,
},
config: {
baseUrl: 'https://your-digitalcx-endpoint',
apiKey: 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx',
culture: 'en'
}
}
const dcxResponse = await doGetRequest(dcxPayload);
const handlerResponse = await dcxResponseHandler({
dcxResponse,
conv,
config
})
const { speech, data, metadata } = handlerResponse
conv.ask(speech.ssml())
})
app.use(bodyParser.json())
app.use('/googleassistant', (req, res, next) => {
googleAssistant({ actionsProject, actionsApp, customIntents })(req, res)
}
`
Build and Test
To run the test suite, first install the dependencies, then run npm test:
`bash
npm i
npm test
``