RingCentral with Automated Web2Campaign using a Google Apps Script
Do you have customers that are tired of long hold times before speaking to an agent? If so, have you considered asking for their contact information so you can call them back when an agent becomes available?
This is what Web2Campaign solves. You create a web form that collects contact information and then turn that contact into a lead for a campaign. Pretty simple concept. I’ve created a version of this to demonstrate how using Google Forms, you can collect a contact’s first name, last name, and phone number to turn them into a lead.
Some Prerequisites
Before we get started, let’s make sure we have a campaign created to add this lead to and also that the agent logging in is assigned this campaign so they can view the leads added to this list. Let’s call this campaign “Google Form Callback” for this example so we are consistent.
Ready? Let’s Go!
Now let’s jump right in and see how it works!
The first step is creating a Google Form to capture your customer’s contact information. With a Google account, you can easily create forms at forms.google.com. You can start with just the simple “Contact Information” form and remove fields you don’t want to include. For my example, I just have the first name, last name, and phone number fields left.
Next, you need to save the responses to a spreadsheet. The easiest method here is to just create a new spreadsheet. So select the “Responses” tab and “Select response destination”. Then “Create a new spreadsheet”.
Now we have a spreadsheet containing all the contacts that wish to be called back. And here is where the API magic comes in. With Google Apps Scripting, we can automatically listen for new contacts and add them to the lead list. The first step is to authorize this Google Apps Script for using the API. Follow this great Google Apps Script Guide from Embbnux to create a sidebar where you can pop-up a login page and authorize this Google Apps Script.
Handle a Form Submit Action
When a contact submits their information, it triggers an onFormSubmit() event. This is the first block of code we have in our script and summarizes everything that is about to happen. Go ahead and copy this code to put in your Apps Script. You can change the campaignName if you have a different one, but for our example we are using the “Google Form Callback”.
function onFormSubmit(e) {
var service = getOAuthService(); // Login to EV using the RC Token
var res = loginEV(service.getAccessToken());
// Grab the account
var account = res.agentDetails[0].accountId;
// Grab the EV token
var eVToken = res.accessToken;
// Find the campaign by name
var campaignName = 'Google Form Callback';
// This user belongs to one account,
// so find the campaign in that account
var campaignId = findCampaignByName(account, campaignName, eVToken);
// Add a number to this campaign
var firstName = e.namedValues['First Name'][0];
var lastName = e.namedValues['Last Name'][0];
var phone = e.namedValues['Phone number'][0]; var leadRes = addLead(account, campaignId, eVToken, firstName, lastName, phone);
}
Trade RingCentral Token for Engage Token
Next we trade that RingCentral token for an Engage Voice token. That means we are logging in to Engage Voice using SSO. To trade tokens add this code to your Google Apps Script.
function loginEV(rcToken) {
var method = 'post';
var path = '/api/auth/login/rc/accesstoken';
var query = '?rcAccessToken=' + rcToken + '&rcTokenType=Bearer';
var headers = { 'Content-Type': 'application/x-www-form-urlencoded' };
return makeEVRequest({method: method, path: path, query: query, headers: headers});
}
The response from this returns two things we are interested in: the Engage access token; and the account ID. Both are returned in the response to the above call.
Make Engage Voice Request Helper
Did you notice something else in the call? We call makeEVRequest() which is a support function to build the API request. Let’s go ahead and add that now.
// Define EV Server
var ENGAGE_SERVER = 'https://engage.ringcentral.com'// Make EV Requests
function makeEVRequest(options) {
var method = options.method;
var path = options.path;
var query = options.query || '';
var body = options.body;
if (body) {
body = JSON.stringify(body);
} else {
body = '';
}
var headers = options.headers;
var response = UrlFetchApp.fetch(ENGAGE_SERVER + path + query, {
headers: headers,
payload: body,
contentType: 'application/json',
method: method || 'get',
muteHttpExceptions: true
});
var json = {};
var code = response.getResponseCode(); // Check return status codes
if (code >= 200 && code < 300) {
json = JSON.parse(response);
return json;
} else if (code == 401 || code == 403) {
console.log(
'error',
'will logout due to get code ',
code,
' when request ',
url,
' with ',
opts
);
service.reset();
throw 'Token expired';
} else {
console.log('error', 'Engage Backend Server Error', path, json);
throw 'Engage Backend Server Error: ' + (json.message || json.error_description);
}
}
Find Campaign By Name
With that out of the way, we can begin looking for the campaign to add this lead to. Engage Voice structures campaigns within a dial group and leads within a campaign. So Dial Groups contain Campaigns which contain Leads. Let’s look for our campaign using the Engage Voice API.
function findCampaignByName(account, name, token) {
// Get dial groups (campaign containers)
var method = 'get'; // Path for dial groups API
var path = '/voice/api/v1/admin/accounts/'+account+'/dialGroups';
var headers = { Authorization: 'Bearer ' + token};
var dialGrpRes = makeEVRequest({method: method, path: path, headers: headers});
for (var i in dialGrpRes) {
var dialGroup = dialGrpRes[i]; // Path for campaigns API
path = '/voice/api/v1/admin/accounts/'+account+'/dialGroups/'+dialGroup.dialGroupId+'/campaigns';
var campaignRes = makeEVRequest({method: method, path: path, headers: headers});
for (var j in campaignRes) {
var campaign = campaignRes[j];
if (campaign.campaignName === name) {
return campaign.campaignId;
}
}
}
throw 'Cannot find the campaign by name '+name+'.';
}
Remember that makeEVRequest() helper function? We are using it again here to make API requests for Dial Groups and Campaigns. We are looping through each dial group to find the campaign that matches the one we want to use to store our leads. Once we find a matching campaign, we’ll return the campaign ID so we can use it in our next function to add the lead.
Add Lead to Campaign
Adding leads allows us to have contacts to call back as part of a campaign. This step adds the details the customer gave us as a lead to the call back campaign and this is what the agent connects to once they log in (as seen in the prerequisites). Here’s how we add that lead to the campaign.
function addLead(account, campaignId, token, firstName, lastName, phone) {
method = 'post';
path = '/voice/api/v1/admin/accounts/'+account+'/campaigns/'+campaignId+'/leadLoader/direct';
headers = { Authorization: 'Bearer ' + token};
body = {
description: 'Leads requesting a callback',
dialPriority: 'IMMEDIATE',
duplicateHandling: 'REMOVE_FROM_LIST',
listState: 'ACTIVE',
timeZoneOption: 'NOT_APPLICABLE',
uploadLeads: [{
leadPhone: phone,
externId: '1',
firstName: firstName,
lastName: lastName
}]
}
return makeEVRequest({method: method, path: path, headers: headers, body: body});
}
Noticed we used our handy helper function, makeEVRequst(), again here. This function certainly got a lot of use with our Web2Campaign!
Now that the lead has been automatically added to the campaign, we just need to wait for an agent to check the lead list and see this new lead to call back.
In Conclusion
Hopefully this article gave you some ideas for how to build your own Web2Campaign and inspire you to build your own forms. Please let us know what you think by leaving any questions or comments below.
To learn even more about other features we have make sure to visit our developer site and if you’re ever stuck make sure to go to our developer forum.
Want to stay up to date and in the know about new APIs and features? Join our Game Changer Program and earn great rewards for building your skills and learning more about RingCentral!