- Post History
- Subscribe to RSS Feed
- Mark as New
- Mark as Read
- Bookmark
- Subscribe
- Printer Friendly Page
- Report Inappropriate Content
4 hours ago
Overview
This article demonstrates how to implement a custom pop-up modal inside a web view (iframe) in Now Mobile or Agent Mobile to prompt users for an in-app review on the Apple App Store or Google Play Store.
This approach is helpful for gathering feedback and improving app visibility directly from within the mobile experience.
Of course, the pop-up can also be done with a mobile event OOTB, but for those pages that use a web view, a widget implementation is required.
Prerequisites
To embed a portal page with widgets inside Now Mobile, follow this guide:
🔗 https://www.servicenow.com/community/mobile-apps-platform-articles/how-to-display-a-portal-page-with...
Step-by-Step Implementation
1. Create a Widget with a Modal Popup
Use the following HTML and AngularJS snippet in your widget:
2. Client Script Logic
c.showFeedbackModal = false;
setTimeout(function() {
$scope.$apply(function() {
c.data.action = "getPreference";
c.server.update().then(function() {
if (c.data.showPopup) {
c.showFeedbackModal = true;
}
});
});
}, 2000); // Show after 2 seconds
c.redirectToStore = function() {
c.data.navUser = navigator.userAgent;
if (/iPhone|iPad|iPod/i.test(navigator.userAgent) && /snMobile/i.test(navigator.userAgent)) {
c.data.action = "redirectiOS";
} else if (/Android/i.test(navigator.userAgent) && /snMobile/i.test(navigator.userAgent)) {
c.data.action = "redirectAndroid";
}
c.server.update().then(function() {
window.open(c.data.redirectStore, "_blank");
c.showFeedbackModal = false;
});
};
c.closeModal = function() {
c.data.action = "getSNFeedback";
c.server.update().then(function() {
$location.url(c.data.dynamicPath);
c.showFeedbackModal = false;
});
};
3. Server Script Logic
Handle user preferences and redirection logic:
var futureDate = new GlideDate();
futureDate.addDaysUTC(365);
var actualDate = new GlideDate();
data.redirectStore = "";
if (input && input.action === 'getPreference') {
// Check if user has already responded
var grPreference = new GlideRecord('sys_user_preference');
grPreference.addEncodedQuery('user=' + gs.getUserID() + '^name=inreview.accepted');
grPreference.query();
if (grPreference.next()) {
var grPreferenceFB = new GlideRecord('sys_user_preference');
grPreferenceFB.addEncodedQuery('user=' + gs.getUserID() + '^name=inreview.rejected');
grPreferenceFB.query();
if (grPreferenceFB.next()) {
var upDate = grPreferenceFB.getValue('value');
data.showPopup = (upDate == actualDate);
}
} else {
data.showPopup = true;
grPreference.initialize();
grPreference.setValue('user', gs.getUserID());
grPreference.setValue('name', 'inreview.accepted');
grPreference.setValue('value', true);
grPreference.insert();
}
} else if (input && input.action === 'getSNFeedback' && gs.isMobile()) {
// Save rejection preference
var grPreferenceInsert = new GlideRecord('sys_user_preference');
grPreferenceInsert.addEncodedQuery('user=' + gs.getUserID() + '^name=inreview.rejected');
grPreferenceInsert.query();
if (!grPreferenceInsert.next()) {
grPreferenceInsert.initialize();
grPreferenceInsert.setValue('user', gs.getUserID());
grPreferenceInsert.setValue('name', 'inreview.rejected');
grPreferenceInsert.setValue('value', futureDate);
grPreferenceInsert.insert();
} else {
grPreferenceInsert.setValue('value', futureDate);
grPreferenceInsert.update();
}
//This step occurs if the user clicks "No"; they are then sent to the internal assessment within the app.
var deepLinkGen2 = new global.MobileDeepLinkGenerator('Request');
data.dynamicPath = deepLinkGen2.getUniversalLink('/mesp?id=me_take_assessment&type_id=');
} else if (input && input.action === 'redirectiOS') {
cancelReview();
data.redirectStore = "https://apps.apple.com/app/{APP ID}?action=write-review"; //replace {APP ID} with the specific app id into the Apple Store.
} else if (input && input.action === 'redirectAndroid') {
cancelReview();
data.redirectStore = "https://play.google.com/store/apps/details?id={APP ID}"; //replace {APP ID} with the specific app id into the Apple Store.
}
function cancelReview() {
var grPreferenceCancel = new GlideRecord('sys_user_preference');
grPreferenceCancel.addEncodedQuery('user=' + gs.getUserID() + '^name=inreview.rejected');
grPreferenceCancel.query();
if (grPreferenceCancel.next()) {
grPreferenceCancel.setValue('value', "");
grPreferenceCancel.update();
}
}
Final Notes
- This solution ensures the pop-up only appears once per user unless reset.
- It uses
sys_user_preference
to track feedback status. - The redirection is handled securely and contextually based on the device type.
- 50 Views