
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎06-11-2020 03:15 AM
Hi there, I'm a newbie that feels like I'm trying to do something beyond my skills - so I apologise in advanced if I'm missing any real basics.
Ultimate Goal: Use a Client Script to trigger a Guided Tour when a Case is in a specific state. Once the Tour has been viewed (tourCompleted) or dismissed (tourDismissed), the tour should not start.
I've used a script from Community Member athm (https://community.servicenow.com/community?id=community_article&sys_id=4d846de3db47130023f4a345ca961...) to achieve the conditional triggering. This works like a charm!
I plan to write an entry to "sys_guided_tour_user_overrides" if the user views or dismisses the tour. For now, I have manually added the entry in the table to test whether I can read from the table:
In order to read from the table, I was originally planning to utilise the Script Include "GTAutoLaunchController". However, rather than messing with a "system" Script, I created my own version of it, to allow me to make it Client Callable and mess around with it. From the Client Script, I am attempting a GlideAjax call. But no matter what I have tried, I believe that it's not triggering the script.
I have added gs.info in various places within the Script Include in an attempt to help me troubleshoot, but nothing appears in the System Log (syslog.list).
The Client Script is as follows:
function onChange(control, oldValue, newValue, isLoading, isTemplate) {
if (isLoading || newValue === '') {
return;
}
//If the current state of the form meets your conditions, launch the tour
if(g_form.getValue('resolution_code') != '0'){
var ga = new GlideAjax('sn_tourbuilder.GTAutoLaunchUtils');
ga.addParam('sysparm_name', 'getOverriddenToursForUser');
ga.addParam('sysparm_userID', g_user.userID);
ga.getXML(checkOveride);
g_form.addInfoMessage(JSON.stringify(ga));
}
function checkOveride(response) {
g_form.addInfoMessage("Response was: " + JSON.stringify(response));
var answer = response.responseXML.documentElement.getAttribute("tourId");
g_form.addInfoMessage(JSON.stringify(answer));
// answer = answer.evalJSON();
// g_form.addInfoMessage(answer);
// for (var i=0 ; i < answer.length ; i++) { //Loop into the array
// g_form.addInfoMessage(answer[i].tourID);
}
// }
top.NOW.guidedToursService.startTour("81996c861b515810e8a7eca13d4bcb6c", 0);
//(sys_id of the guided tour you want to launch, step#)
//Check if the guided tour is dismissed by the user, if so then end the tour.
//If not the system will dispaly a message if the user navigates to a different form
//before the completion of the guided tour.
setInterval(function(){
if(top.NOW.guidedToursService.isDismissed){
top.NOW.guidedToursService.endTour();
clearInterval();
}
},2000);
}
The results from the InfoMessages are as follows:
g_form.addInfoMessage(JSON.stringify(ga));
var GTAutoLaunchUtils = Class.create();
var tourTypes = {
SERVICE_PORTAL: 'service_portal',
PLATFORM: 'platform',
CUSTOM: 'custom_ui'
};
GTAutoLaunchUtils.prototype = Object.extendsObject(global.AbstractAjaxProcessor, {
type: 'GTAutoLaunchUtils'
});
GTAutoLaunchUtils.prototype.tableNames = {
tours: 'sys_embedded_tour_guide',
userOverrides: 'sys_guided_tour_user_overrides'
};
insertOverride = function(tourId, userId) {
var rec = new GlideRecord(this.tableNames.userOverrides);
rec.initialize();
rec.tour = tourId;
rec.user = userId;
rec.disable_autolaunch = true;
rec.insert();
};
removeOverrides = function(page, userId, portal) {
var self = this;
var pages = this.getToursForPage(page, portal);
var ids = pages
.map(function(d) { return d.id; })
;
if (ids.length) {
var rec = new GlideRecord(self.tableNames.userOverrides);
if (userId) {
rec.addQuery('user', '=', userId);
}
rec.addQuery('tour', 'IN', ids.join(','));
rec.deleteMultiple();
return {ids: ids};
} else {
return null;
}
};
overrideTourForUser = function(tourId) {
var currentUser = gs.getUser();
var rec = new GlideRecord(this.tableNames.userOverrides);
rec.addQuery('user', '=', currentUser.getID());
rec.addQuery('tour', '=', tourId);
rec.query();
var exists = rec.next();
var tourRecord = new GlideAggregate(this.tableNames.tours);
tourRecord.addQuery('sys_id', '=', tourId);
tourRecord.query();
if(tourRecord.hasNext() && !exists) {
this._insertOverride(tourId, currentUser.getID());
return {msg: this.messages.done};
} else if(tourRecord.hasNext() && exists && !rec.disable_autolaunch){
rec.disable_autolaunch = true;
rec.update();
return {msg: this.messages.done};
}else {
return null;
}
};
overrideAllToursForUserInPage = function(page, portal) {
var self = this;
var currentUser = gs.getUser();
var userId = currentUser.getID();
var res = this._removeOverrides(page, userId, portal);
if (res) {
res.ids.forEach(function(id) {
self._insertOverride(id, userId);
});
return {msg: self.messages.done};
} else {
return null;
}
};
getOverriddenToursForUser = function() {
gs.info("The script ran");
var userID = this.getParameter('sysparm_userID');
var gr = new GlideRecord("sys_guided_tour_user_overrides");
var data = [];
gr.addQuery('user', userID);
gr.addQuery('disable_autolaunch',true);
gr.query();
gs.info("This is killing me, will this work " + gr.tour);
while(gr.next()) {
gs.info("Results from this script " + gr.tour);
var elem = {tourId: '' + gr.tour};
data.push(elem);
}
return data.toString();
};
I have tried to follow all of the advice in GlideAjax Troubleshooting Guide, I've attempted multiple variations on passing arrays, JSON etc. I've tried different methods of logging, but I believe that gs.info is correct for a Scoped Application.
Ultimately, I'm not convinced that the script is being called (due to the lack of logging). I have run a couple basic Background Scripts (in Global scope) to test whether I can indeed get a result back from the table - and I can:
var gr = new GlideRecord('sys_guided_tour_user_overrides');
gr.addQuery('user','a1fa60be1b6e40d044addac3cc4bcbb9');
gr.addQuery('disable_autolaunch',true);
gr.query();
while(gr.next()){
gs.info("Tour ID: " + gr.tour);
}
Returns:
*** Script: Tour ID: 81996c861b515810e8a7eca13d4bcb6c
var gr = new GlideRecord('sys_guided_tour_user_overrides');
gr.addQuery('user','a1fa60be1b6e40d044addac3cc4bcbb9');
gr.addQuery('disable_autolaunch',true);
gr.query();
var data = [];
while(gr.next()){
var elem = {tourId: '' + gr.tour};
data.push(elem);
}
data.toString();
gs.info(JSON.stringify(data));
Returns:
*** Script: [{"tourId":"81996c861b515810e8a7eca13d4bcb6c"}]
I'm totally at a loss and hope you can help/point me in the right direction.
Thanks!
Solved! Go to Solution.
- Labels:
-
Guided Tours

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎06-11-2020 03:54 AM
Hi
I have not tested out, but I think, you closed your Prototype definition TOO early (look at my screenshot).
You need to put all the code within the curly braces, to make them belong to the Class. You put all of your functions outside, which will make them "unreachable".
Below, I copied the starting part of an OOB AJAX Script include. There you can see, that all functions are INSIDE.
Additionally, make sure to name your Script Include EXACTLY as you do in the code.
Let me know if that answers your question and mark my answer as correct/helpful.
Have fun & Enjoy ServiceNow
BR
Dirk

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎06-11-2020 03:43 AM
Hi Hurleybird,
is your client script created in global application or scoped application?
if in global application then you need to check whether the script include is accessible from All application scopes or just within the scope it is created. In the script include check the value of Accessible from it should be All Application scope.
Please mark this accepted and helpful if it helps. Thanks!
Muhammad

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎06-11-2020 03:51 AM

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎06-11-2020 03:53 AM
Can you try running below script in background script to execute script include and see if it prints the log.
var guidedTourUtil = new sn_tourbuilder.GTAutoLaunchUtils();
var userTours = guidedTourUtil.getOverriddenToursForUser();
Muhammad

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎06-11-2020 03:54 AM
Hi
I have not tested out, but I think, you closed your Prototype definition TOO early (look at my screenshot).
You need to put all the code within the curly braces, to make them belong to the Class. You put all of your functions outside, which will make them "unreachable".
Below, I copied the starting part of an OOB AJAX Script include. There you can see, that all functions are INSIDE.
Additionally, make sure to name your Script Include EXACTLY as you do in the code.
Let me know if that answers your question and mark my answer as correct/helpful.
Have fun & Enjoy ServiceNow
BR
Dirk