Please note the information below are strictly for information purposes and are not supported by Parker Software. Any questions on Facebook app creation, should be directed to Facebook support.
Requirements
Requirements
https://{server}/messaging/api/teams?site={domain}
replacing
{server} with the whoson server address and {domain} with the domain configured in WhosOn, for example
https://testing.whoson.com/messaging/api/teams?site=www.whosontest.com
Requirements
Requirements
Requirements
In order to prevent secure fields from showing through in to Upscope, you can add a css class.
This works on any input type and replaces it with a * on the operator side.
The css class to add is: no-upscope
Upscope cookies:
These cookies are used by Upscope to support the co-browse feature and will be present for visitors to your
website if you have enabled Upscope.
_upscope__shortId, it contains the ID of the user
_upscope__region, it contains which region we should connect to
_upscope__waitingForCallAt it contains the date the user was last requesting a cobrowse
_upscope:uniqueConnectionId is in sessionStorage, and it's a uniqueId set for each window.
_upscope:connectionActiveSince is in sessionStorage, and it's the time the visitor went to the site. This is to
determine the order of visitors to show on the visitors list.
apex_test to determine what the
root domain is, but this is being removed
Requirements
Requirements
Requirements
Requirements
Requirements
The Fastviewer feature allows WhosOn operators to view visitor's screens and control them.
Fastviewer remote sessions can be started from the Modern Client when in an active chat. To begin,
click the Start A Remote Control Session button (located in the upper right corner of the client
when in an active chat).
Clicking this button will show the following prompt:
Clicking Start Remote Session will download the Fastviewer client to your PC. Once downloaded, a
link will automatically be sent to the visitor prompting them to download the Fastviewer client also. The client
will show as an .exe file to the visitor.
Once both parties have the Fastviewer clients open, the remote session can begin.
This section details the operator and visitor views
Once the visitor has started the Fastviewer client, they will be prompted to allow access to the operator to view
their screen, and also take control of their PC.
After approving control, the visitor will see a sidebar on the left side of their screen. This allows them to cancel
the screenshare at any time, as well as expand out additional options in the Fastviewer menu:
Note, the operator cannot take control of the visitor's PC unless they explicitly allow access via the above
permission window.
Once the visitor has started the Fastviewer client, the remote session will begin. The operator will then see a similar sidebar to the visitor. This sidebar shows info about the current session, allows the operator to specify a password, lets the operator share their own screen and more.
This drop down area allows the operator to select a screen to share (if they are sharing screens).
The chat drop down tab allows the visitor and operator to chat with each other.
The fileboard menu allows the operator and visitor to exchange files.
To upload a file, click the Upload button and select a file. The recipient will need to click
Download to receive the file on their end.
The audio menu allows the visitor and operator to communicate using connected microphone and speaker, allowing for audio communication. The operator can set the volume of their microphone and speaker here, as well as mute themselves and disable or enable voice communication.
The log will detail events during the remote session, such as new attendees, permission grants etc.
The information tab will show info regarding the current active remote session.
Either the visitor or operator can stop the remote session at any time using the Stop button. This
button is located in the sidebar.
Requirements
In Twilio, follow the below steps to create a number with the correct settings:
Requirements
Please note a Twilio account is required to proceed. For more information visit Twilio
With a number dedicated to WhosOn/WhatsApp messaging selected, a WhatsApp Sender needs to be created for that number. This register the customers Phone Number with WhatsApp and will inform Twilio as to where it should direct incoming messages to. To create one, the follow steps should be performed:
Once a request has been submitted, it will need to be approved by WhatsApp, this may take some time. Should WhatsApp decline, there may be some changes that are required before the sender can be submitted again.
Once the WhatsApp Sender has been created and approved by WhatsApp, it can now be configured to work with Whoson
Requirements
Please note a Twilio account is required to proceed. For more information visit Twilio
Requirements
Requirements
This integration was developed in collaboration with one of our customers, our support desk are unable to assist with implementing or troubleshooting this specific integration.
This guide provides a basic outline of how to update NetSuite customer records with details from live chats.
You will need to send Parker Software your suitlet URL which we will then POST the chat data to.
You need to add your Suitlet URL to the WhosOn Server's Chat Archiving -> Post Chat JSON to URL section of the WhosOn Service Manager.
WhosOn will POST the data to your Suitlet URL with a JSON formatted transcript, like the below:
{
"id": "0e75hw4p6r",
"Site": {
"Domain": "www.parkersoft.co.uk",
"Name": "Parker Software"
},
"Visitor": {
"Name": "Test",
"CompanyName": "Company",
"IPAddress": "0.0.0.0",
"DNS": "parkersoftware.com",
"Page": "settings/TestPage.aspx?domain=www.parkersoft.co.uk",
"EntryAlert": "Default (All Visitors)",
"EmailAddress": "test@test.com",
"PhoneNumber": "",
"VisitNumber": 1,
"VisitDate": "2022-05-26T15:54:52.287",
"FirstPage": "settings/TestPage.aspx?domain=www.parkersoft.co.uk",
"PageViews": 1,
"Referer": "",
"OperatingSystem": "Windows 10",
"Browser": "Chrome 102",
"Prospect": false,
"Customer": false,
"GeoIP": null,
"GeoIPLocation": null,
"Language": "en",
"ContactRecord": {
"Name": "Test",
"EmailAddress": "test@test.com",
"PhoneNumber": "",
"CompanyName": "Test",
"Street": "",
"City": "",
"ZIP": "",
"Country": "",
"WebAddress": "",
"CRMID": "",
"Notes": ""
}
},
"Operators": [
{
"Name": "Training Admininstrator",
"Department": "",
"Skills": "Account Management,Technical Support,Customer Services",
"EmailAddress": "support@parkersoftware.com",
"PhoneNumber": "",
"IsBot": false,
"Username": "TrainingAdmin"
}
],
"Started": "2022-05-26T15:56:18.493",
"Finished": "2022-05-26T16:06:36.62",
"Invited": false,
"Taken": true,
"RequestedDepartment": "",
"RequestedUserName": null,
"RequestedSkills": [
"Technical Support"
],
"RequestedTranslation": false,
"RequestedCallBack": false,
"RequestedCallBackOn": "0001-01-01T00:00:00",
"WaitedForSeconds": 51,
"ChattedForSeconds": 618,
"PreChatSurvey": [
{
"FieldName": "Company",
"FieldValue": "Company"
},
{
"FieldName": "Product",
"FieldValue": "WhosOn"
},
{
"FieldName": "Department",
"FieldValue": "Technical Support"
}
],
"PostChatSurvey": [
{
"FieldName": "NPS",
"FieldValue": "10"
},
{
"FieldName": "UpgradeTranscript",
"FieldValue": "test@test.com"
}
],
"Transcript": [
{
"Number": 1,
"Dated": "2022-05-26T15:55:27.467",
"IsLink": false,
"IsVisitor": false,
"IsOperator": true,
"IsServerMessage": true,
"OperatorName": "Parker Software",
"Translated": "",
"FileName": null,
"FileURL": null,
"Text": "Chat Matched skill rule: Technical Support"
},
{
"Number": 2,
"Dated": "2022-05-26T15:55:27.467",
"IsLink": false,
"IsVisitor": false,
"IsOperator": true,
"IsServerMessage": true,
"OperatorName": null,
"Translated": "",
"FileName": null,
"FileURL": null,
"Text": "[MR] Chat Matched skill rule: Technical Support"
},
{
"Number": 3,
"Dated": "2022-05-26T15:55:27.577",
"IsLink": false,
"IsVisitor": false,
"IsOperator": true,
"IsServerMessage": true,
"OperatorName": "Parker Software",
"Translated": "",
"FileName": null,
"FileURL": null,
"Text": "Please wait. An operator will be with you shortly."
},
{
"Number": 4,
"Dated": "2022-05-26T15:55:42.973",
"IsLink": false,
"IsVisitor": false,
"IsOperator": true,
"IsServerMessage": true,
"OperatorName": "Parker Software",
"Translated": "",
"FileName": null,
"FileURL": null,
"Text": "One moment please..."
},
{
"Number": 5,
"Dated": "2022-05-26T15:55:57.577",
"IsLink": false,
"IsVisitor": false,
"IsOperator": true,
"IsServerMessage": true,
"OperatorName": "Parker Software",
"Translated": "",
"FileName": null,
"FileURL": null,
"Text": "Sorry for the delay..."
},
{
"Number": 6,
"Dated": "2022-05-26T15:56:18.493",
"IsLink": false,
"IsVisitor": false,
"IsOperator": true,
"IsServerMessage": true,
"OperatorName": null,
"Translated": "",
"FileName": null,
"FileURL": null,
"Text": "[OP] Operator daniel.horton picked up chat session. (Test)"
},
{
"Number": 7,
"Dated": "2022-05-26T15:56:33.167",
"IsLink": false,
"IsVisitor": false,
"IsOperator": true,
"IsServerMessage": false,
"OperatorName": null,
"Translated": "",
"FileName": null,
"FileURL": null,
"Text": "Something to test with"
},
{
"Number": 8,
"Dated": "2022-05-26T15:56:33.167",
"IsLink": false,
"IsVisitor": false,
"IsOperator": true,
"IsServerMessage": true,
"OperatorName": null,
"Translated": "",
"FileName": null,
"FileURL": null,
"Text": "[FL1] First line received from operator. (Test)"
},
{
"Number": 9,
"Dated": "2022-05-26T15:56:41.71",
"IsLink": false,
"IsVisitor": true,
"IsOperator": false,
"IsServerMessage": false,
"OperatorName": null,
"Translated": "",
"FileName": null,
"FileURL": null,
"Text": "Response"
},
{
"Number": 10,
"Dated": "2022-05-26T15:56:45.893",
"IsLink": false,
"IsVisitor": false,
"IsOperator": true,
"IsServerMessage": false,
"OperatorName": null,
"Translated": "",
"FileName": null,
"FileURL": null,
"Text": "Reply"
},
{
"Number": 11,
"Dated": "2022-05-26T16:00:36.077",
"IsLink": false,
"IsVisitor": false,
"IsOperator": true,
"IsServerMessage": false,
"OperatorName": null,
"Translated": "",
"FileName": null,
"FileURL": null,
"Text": "# Markdown\r\n\r\nCanned Responses and operator sent lines can now contain **MarkDown**\r\n \r\nMarkdown can be **bold** *italics* ~~strikethru~~\r\n\r\n 1. List item1\r\n 2. List item2\r\n\r\n| Tables | Are | Cool |\r\n| ------------- |:--------------:| -------:|\r\n| col 3 is | right-aligned | $1600 |\r\n| col 2 is | centered | $12 |\r\n\r\n> This is a note\r\n\r\n```\r\nthis is a code block\r\n```\r\n\r\n> For more info see:\r\n> [MarkDown Guide](https://www.markdownguide.org/cheat-sheet/)\r\n\r\nEmbedded Image ![WhosOn](https://www.whoson.com/img/whoson-logo-sm.png)"
},
{
"Number": 12,
"Dated": "2022-05-26T16:02:51.65",
"IsLink": false,
"IsVisitor": true,
"IsOperator": false,
"IsServerMessage": false,
"OperatorName": null,
"Translated": "",
"FileName": null,
"FileURL": null,
"Text": "Can you please tell me about your GDRP policy?"
},
{
"Number": 13,
"Dated": "2022-05-26T16:03:25.39",
"IsLink": false,
"IsVisitor": true,
"IsOperator": false,
"IsServerMessage": false,
"OperatorName": null,
"Translated": "",
"FileName": null,
"FileURL": null,
"Text": "GDPR Policy"
},
{
"Number": 14,
"Dated": "2022-05-26T16:03:59.883",
"IsLink": false,
"IsVisitor": false,
"IsOperator": true,
"IsServerMessage": false,
"OperatorName": null,
"Translated": "",
"FileName": null,
"FileURL": null,
"Text": "We have all the details for WhosOn's GDPR compliance on https://www.whoson.com/product/security/gdpr/"
},
{
"Number": 15,
"Dated": "2022-05-26T16:05:43",
"IsLink": false,
"IsVisitor": true,
"IsOperator": false,
"IsServerMessage": false,
"OperatorName": null,
"Translated": "",
"FileName": null,
"FileURL": null,
"Text": "Response"
},
{
"Number": 16,
"Dated": "2022-05-26T16:06:36.62",
"IsLink": false,
"IsVisitor": false,
"IsOperator": true,
"IsServerMessage": false,
"OperatorName": null,
"Translated": "",
"FileName": null,
"FileURL": null,
"Text": "Reply"
},
{
"Number": 17,
"Dated": "2022-05-26T16:15:38.9",
"IsLink": false,
"IsVisitor": false,
"IsOperator": true,
"IsServerMessage": true,
"OperatorName": null,
"Translated": "",
"FileName": null,
"FileURL": null,
"Text": "[OC] Operator daniel.horton forced closed session."
},
{
"Number": 18,
"Dated": "2022-05-26T16:15:38.913",
"IsLink": false,
"IsVisitor": false,
"IsOperator": true,
"IsServerMessage": true,
"OperatorName": "Parker Software",
"Translated": "",
"FileName": null,
"FileURL": null,
"Text": "Operator daniel.horton forced closed session."
},
{
"Number": 19,
"Dated": "2022-05-26T16:16:13.517",
"IsLink": false,
"IsVisitor": false,
"IsOperator": true,
"IsServerMessage": true,
"OperatorName": null,
"Translated": "",
"FileName": null,
"FileURL": null,
"Text": "[PS] Post-chat survey submitted (Test)"
},
{
"Number": 20,
"Dated": "2022-05-26T16:16:14.127",
"IsLink": false,
"IsVisitor": false,
"IsOperator": true,
"IsServerMessage": false,
"OperatorName": null,
"Translated": "",
"FileName": null,
"FileURL": null,
"Text": "Email sent to test@test.com for site: Parker Software"
}
],
"TelephoneCalls": null,
"Rating": 0,
"SentimentScore": 0,
"WrapUpValue": "Demonstration",
"Tags": null,
"Missed": false,
"MissedResponded": false,
"MissedRespondedBy": null,
"MissedRespondedDate": "0001-01-01T00:00:00",
"Summary": "Canned responses and operator sent lines can now contain markdown.",
"LeftMessageMessage": "",
"TranscriptURL": "https://chat.whoson.com/whosoncharts/chatview.aspx",
"WebServicesURL": "https://chat.whoson.com/whosoncharts/"
}
Using Suitlets you can script how NetSuite processes the data and how it appends it to your customer records within
NetSuite.
You can review NetSuite's documentation on Suitlets to assist you in building your Suitlet:
https://docs.oracle.com/en/cloud/saas/netsuite/ns-online-help/section_4387799600.html
https://docs.oracle.com/en/cloud/saas/netsuite/ns-online-help/article_159074784880.html
Here is an example of the script used by one of our customers:
/**
* Copyright Holcros Ltd 2022
*
* @summary Logs Live-Chats from WhosOn against the customer's profile
*
* @author Daniel Saunders
*
* Created at : 2022-06-15 10:33
* Last modified : 2022-06-20 16:06
*
*
* @NApiVersion 2.x
* @NScriptType Suitelet
* @NModuleScope SameAccount
*/
define(['N/record', 'N/search', 'N/log', 'N/email', 'N/render'],
function( m_record, m_search, m_log, m_email, m_render) {
var data = {};
/*
Script Entry Point
*/
function onRequest(context) {
data.context = context;
if(context.request.method === 'POST') {
// The method was a POST request
var responceJson = processPOST();
return data.context.response.write(JSON.stringify(responceJson));
} else {
// the method was not a POST request
return null;
}
}
/*
Functions
*/
function DebugMessage(n,g){string_chop=function(n,g){return null==n?[]:(n=String(n),(g=~~g)>0?n.match(new RegExp(".{1,"+g+"}","g")):[n])};for(var t=string_chop(g,999),e=0;e<t.length;e++)m_log.debug(n,t[e])}
function processPOST() {
try {
// Extract the caller's IP from the request header
var requestFrom = data.context.request.clientIpAddress;
// Extract the data from the request body
var requestBody = data.context.request.body;
// Check to payload to ensure that it contains data
if(requestBody == null) { throw 'Request payload was missing'; }
if(requestBody.length == 0) { throw 'Request payload was empty'; }
// Try to decode the payload
var payload = null;
try {
payload = JSON.parse(requestBody);
}
catch(err) { throw 'Request payload was not in the correct format'; }
DebugMessage('payload', JSON.stringify(payload) );
// Check the email address exists
var lookupEmailAddress = payload.Visitor.EmailAddress;
// If there was not an email address in the visitor header, pull it from the pre-chat survey directly
if(lookupEmailAddress == null) {
for(var i = 0; i < payload.PreChatSurvey.length; i++) {
if(payload.PreChatSurvey[i].FieldName == "email") {
lookupEmailAddress = payload.PreChatSurvey[i].FieldValue;
}
}
}
if(lookupEmailAddress == null) { throw 'A Required Parameter was not set'; }
// Log the request
DebugMessage('Post Request', "Chat transcript for " + JSON.stringify(lookupEmailAddress) + " posted by " + JSON.stringify(requestFrom) );
// Check if the chat already exists by searching for its ID in the title,
// so that we can create the chat if it doesn't exist, or update the existing message.
var callSearch = m_search.create({
type: m_search.Type.PHONE_CALL,
title: 'WOA - Call Lookup',
id: 'customsearch_woa_calllookup',
columns: [
{ name: 'internalid' }, { name: 'externalid' }
],
filters: [
{ name: 'formulanumeric', operator: m_search.Operator.EQUALTO, formula: "CASE WHEN ( {title} LIKE '% | " + payload.id + "') THEN 1 ELSE 0 END", values: [ 1 ] }
]
});
var callResults = callSearch.run().getRange({ start: 0, end: 1 });
// If the chat record exists, store its ID in callInternalID
var callInternalID = null;
if(callResults.length > 0) {
callInternalID = callResults[0].getValue('internalid');
}
// Extract the customer name from the request
var customerName = payload.Visitor.Name;
// In case we can't access an operator name on the line level
// (for some reason it's sometimes null?)
var fallbackOperatorName = '';
if(payload.Operators) {
if(payload.Operators.length > 0) {
if(payload.Operators[0].Name) {
fallbackOperatorName = payload.Operators[0].Name;
}
}
}
var phoneCall = null;
if(callInternalID == null) {
/*
Existing Call - Update the chat log
*/
// Try to extract the sales order number and the case number from the pre-chat survey
var prechatSalesOrderNumber = null;
var prechatSupportCaseNumber = null;
for(var i = 0; i < payload.PreChatSurvey.length; i++) {
if(payload.PreChatSurvey[i].FieldName == "SaleOrderNumber") {
prechatSalesOrderNumber = payload.PreChatSurvey[i].FieldValue;
}
if(payload.PreChatSurvey[i].FieldName == "SupportCaseNumber") {
prechatSupportCaseNumber = payload.PreChatSurvey[i].FieldValue;
}
}
// Find the internalid of the customer customer from the email address
var customerSearch = m_search.create({
type: m_search.Type.CUSTOMER,
title: 'WOA - Customer Lookup',
id: 'customsearch_woa_customerlookup',
columns: [
{ name: 'internalid' }, { name: 'entityid' }
],
filters: [
{ name: 'email', operator: 'is', values: [lookupEmailAddress] }
]
});
var customerResults = customerSearch.run().getRange({ start: 0, end: 1 });
// If the customer record exists, store its ID in customerID
var customerID = null;
if(customerResults.length > 0) {
customerID = customerResults[0].getValue('internalid');
}
// Find the internalid of the support case from the case number
var caseID = null;
if(prechatSupportCaseNumber) {
var caseSearch = m_search.create({
type: m_search.Type.SUPPORT_CASE,
title: 'WOA - Case Lookup',
id: 'customsearch_woa_caselookup',
columns: [
{ name: 'internalid' }, { name: 'casenumber' }
],
filters: [
{ name: 'casenumber', operator: 'is', values: [ prechatSupportCaseNumber ] }
]
});
var caseResults = caseSearch.run().getRange({ start: 0, end: 1 });
// If the case record exists, store its ID in caseID
if(caseResults.length > 0) {
caseID = caseResults[0].getValue('internalid');
}
}
// Find the internalid of the Sales Order from the sales order number
var transactionID = null;
if(prechatSalesOrderNumber) {
var transactionSearch = m_search.create({
type: m_search.Type.SALES_ORDER,
title: 'WOA - Transaction Lookup',
id: 'customsearch_woa_transactionlookup',
columns: [
{ name: 'internalid' }, { name: 'tranid' }, { name: 'entity' }
],
filters: [
{ name: 'tranid', operator: 'is', values: [ prechatSalesOrderNumber ] }
]
});
var transactionResults = transactionSearch.run().getRange({ start: 0, end: 1 });
// If the sales order record exists, store its ID in transactionID
if(transactionResults.length > 0) {
transactionID = transactionResults[0].getValue('internalid');
// Force the customer to be this one - in case they have more than one profile somehow
DebugMessage('Customer Force Change', JSON.stringify(customerID) + ' -> ' + JSON.stringify(transactionResults[0].getValue('entity')) + ' - changed to match sales order' );
customerID = transactionResults[0].getValue('entity');
}
}
// Create the chat record as a phone call
phoneCall = m_record.create({
type: m_record.Type.PHONE_CALL,
isDynamic: true
});
// If a customer record matched an email address, link it to the chat
if(customerID) {
phoneCall.setValue({ fieldId: 'company', value: customerID, ignoreFieldChange: true });
}
// If a phone number was present, add it to the chat
if(payload.Visitor.PhoneNumber) {
if(payload.Visitor.PhoneNumber.length > 6) {
phoneCall.setValue({ fieldId: 'phone', value: payload.Visitor.PhoneNumber, ignoreFieldChange: true });
}
}
// Set the chat's title, including the id
phoneCall.setValue({ fieldId: 'title', value: 'Live Chat With ' + payload.Operators[0].Name + ' | ' + payload.id, ignoreFieldChange: true });
// Mark the status of the call complete
phoneCall.setValue({ fieldId: 'status', value: 'COMPLETE', ignoreFieldChange: true });
// Organiser - If we don't set it NetSuite marks it as "System"
////phoneCall.setValue({ fieldId: 'assigned', value: -1, ignoreFieldChange: true });
// Set the date of the chat from the request
var d = new Date();
phoneCall.setValue({ fieldId: 'startdate', value: d, ignoreFieldChange: true });
// If a support case record matched an id, link it to the chat
if(caseID) {
phoneCall.setValue({ fieldId: 'supportcase', value: caseID, ignoreFieldChange: true });
}
// If a sales order record matched an id, link it to the chat
if(transactionID) {
phoneCall.setValue({ fieldId: 'transaction', value: transactionID, ignoreFieldChange: true });
}
// Log the successful creation of the chat log
DebugMessage('Created', "Created new call");
} else {
/*
Existing Call
*/
// load the existing call record
phoneCall = m_record.load({
type: m_record.Type.PHONE_CALL,
id: callInternalID,
isDynamic: true
});
// Log the successful update of the chat record
DebugMessage('Updated', "Updated call " + JSON.stringify(callInternalID));
}
// Message field variable
var messages = "";
// Add the Pre-Chat Survey to the message field
messages += 'Pre Chat Survey:\n';
if(payload.PreChatSurvey) {
for(var i = 0; i < payload.PreChatSurvey.length; i++) {
messages += payload.PreChatSurvey[i].FieldName + ': ' + payload.PreChatSurvey[i].FieldValue + '\n';
}
}
messages += '-----------\n';
// Add the Post-Chat Survey to the message field
messages += 'Post Chat Survey:\n';
if(payload.PostChatSurvey) {
for(var i = 0; i < payload.PostChatSurvey.length; i++) {
messages += payload.PostChatSurvey[i].FieldName + ': ' + payload.PostChatSurvey[i].FieldValue + '\n';
}
}
messages += '-----------\n';
// Add the Tags to the message field
if(payload.Tags) {
messages += 'Tags:' + payload.Tags.join(',') + '\n';
}
// Add the Wrap Up Value to the message field
if(payload.WrapUpValue) {
messages += 'Wrap Up: ' + payload.WrapUpValue + '\n';
}
messages += '-----------\n\n';
// Add the Chat Messages to the message field
for(var i = 0; i < payload.Transcript.length; i++) {
if(payload.Transcript[i].IsServerMessage) {
// Server messages
messages += '🖥 ' + payload.Transcript[i].Text + '\n\n';
}
else if(payload.Transcript[i].IsOperator) {
// Operator messages
if(payload.Transcript[i].OperatorName) {
messages += '🤵(' + payload.Transcript[i].OperatorName + '): ' + payload.Transcript[i].Text + '\n\n';
} else {
messages += '🤵(' + fallbackOperatorName + '): ' + payload.Transcript[i].Text + '\n\n';
}
}
else if(payload.Transcript[i].IsVisitor) {
// Customer messages
messages += '🧝(' + customerName + '): ' + payload.Transcript[i].Text + '\n\n';
}
else {
// Other messages - links and such
messages += '📕 <' + payload.Transcript[i].Text + '>\n\n';
}
}
// If the message is too long for the field make a note of it in the logs
if(messages.length > 4000) {
DebugMessage('Warning', "Chat log truncated to 4000 characters ");
}
// truncate to the max length of 4000 characters.
phoneCall.setValue({ fieldId: 'message', value: messages.substring(0, 4000), ignoreFieldChange: true });
// Save the chat log
var callID = phoneCall.save({
enableSourcing: false,
ignoreMandatoryFields: false
});
// Return OK to the requesting server
return {success: true, message: "OK"};
}
catch(err) {
// Log the error
m_log.error({ title: 'Error', details: JSON.stringify(err.message) });
m_log.debug({ title: 'Debug', details: JSON.stringify(err) });
// Return the error to the requesting server
return {success: false, message: JSON.stringify(err.message)};
}
// This can't happen, but if it does, return the error to the requesting server
return {success: false, message: "General Error"};
}
return {
// Register the entrypoint with NetSuite
onRequest: onRequest
};
});