The Now Platform® Washington DC release is live. Watch now!

Help
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
Maik Skoddow
Tera Patron
Tera Patron
MaikSkoddow_0-1665127842675.jpeg
I know, I'm not the first one who presents such a list of tips and tricks for working with ServiceNow, but for me it is the only way to have everything on one page. I have posted most of the items below on my LinkedIn profile, but there it takes several minutes to load all my posts and thus is really frustrating just for checking a fact I cannot remember any more.
 
I recommend bookmarking this article so that you are automatically notified by email when changes are made by me.

 

 

Development | Security
The following code line elevates the currently logged-in user to the given role. Useful for script-based setting up an instance or user provisioning:
 
GlideSecurityManager.get().enableElevatedRole('security_admin');

 

 

Implementation | Flow Designer
If you want to determine which Flows are triggered for a certain table you can perform the following script:
 
var grActionInstance = new GlideAggregate('sys_hub_action_instance');
var strTableName = 'wm_task'; //replace with your table name

grActionInstance
    .addJoinQuery('sys_variable_value', 'sys_id', 'document_key')
    .addCondition('value', strTableName);
grActionInstance.addAggregate('GROUP_CONCAT_DISTINCT', 'flow'); 
grActionInstance.groupBy('flow');
grActionInstance.addQuery('flow.sys_class_name', 'sys_hub_flow')
grActionInstance.query();

while(grActionInstance.next()) {
    gs.info(
        '[{0}]\t{1}', 
        grActionInstance.flow.active ? 'active' : 'inactive', 
        grActionInstance.flow.name
    );
}

 

 

Implementation
Have you ever been annoyed by the fact that the two relationships "Updates" & "Versions" are missing in the form view, even though they are essential for development? For this reason, I created another helpful Business Rule which adds these two relationships automatically whenever a record from a child table of sys_metadata is modified.
 
MaikSkoddow_0-1705115919696.png

 

 

Implementation | Flow Designer
Sometimes it is required to retrieve the Flow's context id (record at table sys_flow_context) for a certain implementation. Fortunately there is a API for that purpose: 
var _strContextID = FlowScriptAPI.getContextID();

 

 

Basics
See the semaphore concept of ServiceNow in action: The application repository is nothing else than a ServiceNow instance. If too many customer instances in this world want to install an application at the same time, it might be blocked due to missing empty slots in the app repo's semaphore queue. As a result, the application installation will fail and your only chance is to try the whole process again at a later time.
 
MaikSkoddow_1-1705116112514.png

 

 

Basics
Recently I came across an interesting finding by chance. If you call the module "Logged in users" (opens virtual table v_user_session) you might see who is currently being impersonated by whom. Of course, this only applies to the current node on which you are logged in.
 
MaikSkoddow_2-1705116591673.png

 

 

Development
If you want to enhance your script performance via caching "expensive" data structures within the session object, you should keep in mind that impersonating does not create a new session. The impersonated user therefore has full access to the data previously stored by the other user in the session! If this is not desired, simply work with unique prefixes for the keys:
 
MaikSkoddow_2-1700856569979.png

 

 

UI | List View
Recently I was asked on LinkedIn how to search for "DOES NOT START WITH" in the list view. Unfortunately, I could not find a way so far, but that scenario is definitely possible with a GlideRecord query by combining "NOT LIKE" operation and "%" within the search term. See the following example, which demonstrates how to query all UI Actions not starting with "Open in":
 
MaikSkoddow_3-1705116842266.png

 

 

UI | List View
You might know that in the list view, there is no operator "is not one of" for string-based fields in the query builder. So, how to exclude for example a longer list of Sys IDs from a result list? Fortunately, there is a workaround to achieve that scenario:
  1. Search for "is one of" as usual. Then replace within the URL the operator "IN" with "NOT IN" and perform the search again. In the query builder you now can find the option "NOT IN".
  2. Fill in the list of comma-separated values you want to exclude. With Sys IDs the resulting URL might become too long. In that case, it is shortened automatically by ServiceNow.
 
MaikSkoddow_0-1700855969776.png

 

 

 

Administration | Audit Logs
The sys_audit_delete and sys_audit_relation tables are used to store information about deleted records and their relationships to other records, and thus facilitating an "Undelete" capability. Unchecked, these tables can grow very large and cause wider performance issues. Unfortunately, in a baseline instance, there is no feature active to maintain the these tables automatically. However, ServiceNow provides a KB article and a script you can perform to do that job.
 

 

 

Administration | Audit Logs
If you have many users in your ServiceNow instance who often use a mobile app (e.g. FSM agents) or you generally work a lot with OAuth-based authentication, you should set the attribute "no_audit_delete=true" for the oauth_credential table. Otherwise, the sys_audit_delete and sys_audit_relation tables will grow quickly, as OAuth tokens are permanently deleted by ServiceNow when they expire. However, restoring them does not add any value and you can dispense with deletion auditing for this data. 
 
MaikSkoddow_0-1700278008158.png

 

 

Implementation | Unknown Tables
If the Mobile Card Builder or a Workspace (e.g. the FSM Dispatcher Workspace) is getting stuck while initial loading, it might be that the server requests executed in the background took too long and ServiceNow cancelled the transactions. You can check this in the Transaction Cancellation Log (syslog_cancellation). If you find such cancellations there, adjust the corresponding Transaction Quota Rules.

MaikSkoddow_0-1695529067630.png

 

 

Development | Unknown APIs
For validating IPv4 or IPv6 addresses in ServiceNow, you can use the undocumented factories SncIPAddressV4 and SncIPAddressV6:

screenshot.png

 

 

ServiceNow Ecosystem | NowLearning
The search experience in the NowLearning portal is rather badly. For example there is no way any more to browse freely through all courses as you always have to specify a search term. But what should you enter if you cannot name what to search for? Fortunately there is a workaround. To get a list of all courses just enter three stars ("***"). Then add filters like "On-Demand" and/or "Free" to narrow down the result list to relevant entries:

MaikSkoddow_0-1691153404190.png

 

 

 

ServiceNow Ecosystem | Documentation Portal
With the two family releases per year, the links to the documentation pages are constantly changing because the family name is part of the URL:
 
https://docs.servicenow.com/bundle/utah-build-workflows/page/administer/notification/task/deactivate-stop-processing.html
 
However there is a short format which will always redirect to the latest family release version of a page. To do this just take the last part of the URL and append it to the following version:

 

 

Implementation | UI Actions
If you want to disable an OOTB UI Action without touching it (yes, also without setting "active" to "false"!) you can add the "nobody" role. That role assignment can be captured in your own application. And instead of ACLs you can remove it again without any problems. 
 
MaikSkoddow_1-1690168226869.png

 

 

Development | Skipped Records
After going into the wrong direction for some time (but thanks to Jochen Geist I learned something new: KB0794114 ) it turned out that my issues regarding missing deletions on higher instances was related to skipped records. Therefore, always look out for the following entries in the sys_plugin_log table after an app installation. Then go to table sys_upgrade_history_log and process the skipped records..
 
MaikSkoddow_0-1690167843833.png

 

 

Implementation | Customization
Before every ServiceNow family release, you're served the ever-unpopular list of skipped records, and as you try several hundred times to make the right decision, you wonder once again why you haven't paid more attention to making sure your developers don't customize OOTB artifacts. To raise awareness of this thorny issue and increase visibility, I've added one more to my best-of list of useful business rules, which displays an appropriate warning when you open a modified OOTB artifact. That warning message also provides a link to the most recent OOTB version, where you will find a UI Action for reverting to that version.
 
MaikSkoddow_0-1688087728626.png

 

 

Administration | Maintenance
When you have a ServiceNow instance that is pumped with many file attachments, it is advisable to check the total size of all attachments from time to time. This is because file attachments are not stored in the file system, but in the database, which - depending on the contract - has a limited size (usually 2 TB). I know that the final consumed database space is even larger, but I just wanted to have a quick overview.
 
MaikSkoddow_1-1688087933641.png

 

 

Implementation | Customization
I recently accidentally clicked the "Debug Upgrade" module in ServiceNow and was very surprised at the result. After the next page reload, if you scroll to the bottom, you will see a list of all the changed OOTB artifacts that were involved in the corresponding client transaction. This way the development lead or architect has an easy way to find out what his developers have (unintentionally) changed and thus would be listed as a skipped record in the next upgrade.
 
MaikSkoddow_2-1688088084404.png

 

 

Implementation | Unknown Tables
You probably already know these progress bars which represent long-running background processes. And of course they are back-boned by a table - in that case by sys_execution_tracker. If you are fast enough, you can open the related record & watch the progress. The real-time updates of new values in the form is one of my favorite capabilities in ServiceNow..
 
Animation.gif

 

 

Administration | Monitoring
You probably already know the page /xmlstats.do, which provides an unbelievable number of technical metrics - but only for the application node you are currently logged in to. The returned values are separated by topics which are listed at the "includes" attribute of the XML root element and it seems that this page lists nearly everything which is available. If you want to get these values for all nodes of your instance, you can use the following small script. It iterates over the records of the table sys_cluster_state which represent one node each and then reads the statistics. A JavaScript object is then created via the XmlHelper API, which simplifies access to the underlying values enormously. The topics contained in the XML obtained in this way are controlled by the "glide.cluster.xmlstats" system property. That way you can add more topics here, for example "plugins", to get a list of all installed plugins/apps on a node. Based on this data, you can now develop a kind of monitoring app that visualizes the health status of all nodes and sends warnings if certain values reach a critical range (for example, the available memory falls below a certain threshold).

MaikSkoddow_3-1682744336598.png

 

 

Administration | Maintenance
Everyone is always talking about instance upgrades, but there is little information about the fact that the installed plugins and apps must also be permanently checked and evaluated for new versions. But how do you find out that there are new versions available? You could open the plugin application (/$allappsmgmt.do) and drill-down with the "Updates" filter. However, this is a manual activity without any chance for automated notifications. So is there an alternative? If you are logged in as admin user, you can find a score "Ready to update" on the admin center home page (/now/nav/ui/home). How is this score calculated? There is a scheduled job "App Status Count" which determines all applications ready for update or initial installation. These two numbers are then written to the table polaris_app_shell_app_counts. With a Business Rule, you could monitor changes to this number and then react accordingly. Unfortunately, this approach does not provide more information like app names or versions. Therefore, I extracted the code to get the detailed list of all apps which are ready for updating.

MaikSkoddow_2-1682744162110.png

 

 

Development
In case you made the mistake to extend a custom table of a scoped application from the wrong parent table (for example sysauto instead of sysauto_script). Because of the many artifacts I had already created, I didn't want to start from scratch and luckily found the API GlideTableParentChange, which made re-parenting a painless task.

MaikSkoddow_1-1682743988463.png

 

 

ServiceNow Ecosystem | Application Repository
Did you know, that with a ServiceNow Support/Store account, you also can log in to the Application Repository as well? It is just another ServiceNow instance at https://apprepo.service-now.com/. Basically, you cannot do much there, but it is interesting to see which applications are managed under the umbrella of your company. I don't want to imagine what happens if that instance is broken 😯. And also don't forget to whitelist that domain in case you have activated IP address access restrictions in your instances.

MaikSkoddow_0-1682743754313.png

 

 

UI | List View
In ServiceNow it is OOTB not possible to group a GlideList field in the list view. But after adding a dictionary attribute "can_group=true" to the GlideList field, it is nevertheless possible. You can find more interesting facts about GlideList fields in the following knowledge article.
 

 

 

Development | Client-side
Yes, I know: It's not recommended to do DOM manipulations in #ServiceNow client-side scripts. However, sometimes it can't be avoided, for example when you want to control the click behavior of buttons in modals. But for scoped applications it is not enough to set the "Isolate script" field to "false" (e.g. in a UI Action). Additionally, you need to create in your app scope a system property glide.script.block.client.globals with the value "false". See the following Support article for the complete instructions
 

 

 

Administration | Searching
I guess you know that situation. In any of the many artifact types (e.g. "Condition" field of a UI Action) a non-existing method of an existing Script Include is referenced. It seems that this method has fallen victim to an overzealous cleanup, but you need its code to validate whether the invocation is still required or not. Basically, the needed method still exists somewhere in the several hundred entries long version list of the respective Script Include (table sys_update_version). But how to find it? A "CONTAINS" search on the "Payload" field is not possible, because it is of type "Compressed", which apparently does not support such searches. However, there is a second search technology, that of text indexes. Unfortunately the table sys_update_version is not indexed OOTB. After activation and generation of a text index, which can take quite a few hours depending on the number of records, a new entry "for text" is available in the field selection at the top of the list view. Now, finally, the search for the method name brings the corresponding versions in the light.
 
MaikSkoddow_1-1680706922180.png

 

 

Next Experience UI | Theme Builder
If you define a new logo in the Next Experience Theme Builder you also have to set the system property glide.ui.polaris.theme_builder.override_logo to "true". Otherwise the logo is ignored.

 

 

Administration | Maintenance & Performance
By default, there are 4 "Service Mapping Recomputation" jobs per node, on a ServiceNow instance.
When these jobs run for longer time they might impact memory consumption and performance. But if you are not using Service Mapping or Application Services in your CMDB you can disable them. The following knowledge articles explain the reasons and what to do.
 

 

 

Development | Client-side

Your browser provides you with a complete development environment for client-side scripts in ServiceNow. Make sure you opened the page without the frameset (use /pop command from SNUtils if required), then open the Developer Tools (F12), go to "Source" -> "Snippets" and create a new one. The really cool thing is the code completion which reveals ALL methods and properties of an API like g_form. Also, code debugging with breakpoints and variable watching is possible.

MaikSkoddow_0-1678710394639.png

 

 

Development | APIs

There is a API GlideEmailOutbound which allows creating emails directly without utilization of notifications. After invocation of the save() method a record is created at table sys_email. But unfortunately that API does not provides a method for attaching files.

 

var mail = new GlideEmailOutbound();

mail.addAddress('cc', '123@123.com');
mail.addRecipient("abc@abc.com");
mail.setSubject("Test Email");
mail.save();

 

 

Development | APIs

If you need a way to identify the name of the family release your instance is running with, you can use the following method. Another method returns the file name of the latest upgrade version:

 

gs.info(new sn_appclient.GlideUpgradeUtil().getCurrentBuildName());
gs.info(new sn_appclient.GlideUpgradeUtil().getCurrentBuild());
MaikSkoddow_0-1674972223612.png

 

 

Development | APIs

There is an undocumented API which can convert the value from GlideDateTime object into a human readable format, like "3 months from now" or "2 weeks ago":

 

gs.info(new GlideTimeAgo().format(new GlideDateTime('2023-01-08 07:13:22'));

 

 

Administration | Importing Data
By default, when ServiceNow creates a new staging table, it measures the length of the first 20 records to determine how long the fields should be. If the data values to be imported exceed the length of the fields in the staging tables, they will be truncated and not imported properly.
To prevent truncating you can set the system property com.glide.loader.verify_target_field_size to "true".
That way ServiceNow will automatically expand the staging table values based on incoming data, even after the first 20 records have been imported.

 

 

Administration | Update Sets
Have you ever noticed the related link "Show all preview records" on the form for previewing an Update Set? This will lead you to a much better comparison of differences between local artifacts and those from an update set to be committed in ServiceNow
 
Enhanced Preview Update Set Collisions.png

 

 

Basics 
If you are in a customer-facing role for a ServiceNow project, you have to be prepared to many questions about ServiceNow as a PaaS / SaaS provider. Questions like "Has ServiceNow access to my sensitive data?" or "Does ServiceNow comply to the European GDPR?". Such questions are basically answered in the Knowledge Base "Trust, Privacy & Compliance" at the support portal. And while the more than 160 articles contained therein are public, the knowledge base itself can only be accessed after logging into the support portal. This makes it very difficult for most users to get an overview and search/consume the contents in a focused way. For this reason, I decided to extract all articles and combine them into one document. While doing this I learned a lot and I highly recommend reading that document.
 
 
MaikSkoddow_0-1673503217112.png

 

 

Administration | Audit Logs
If a regulation or your security department requires you to enable audit log of the sys_user table in ServiceNow, be careful! After ticking the "Audit" checkbox in the dictionary, your audit log will be flooded with a lot of information that might not be required (for example last login times). Instead, use the whitelist approach and enable auditing only for those fields which are of interest. For more information, see https://support.servicenow.com/kb?id=kb_article_view&sysparm_article=KB0869832 

 

 

Implementation | Forms
Form layout problems in ServidceNow are always a guarantee for headaches. Thankfully, there is a knowledge article that clearly explains the relationships between the various artifacts and how to manually fix broken form layouts: https://support.servicenow.com/kb?id=kb_article_view&sysparm_article=KB0635235 
However, if you want to easily find out what exactly has changed in the current layout version compared to the last version, I recommend the following article: UI Action to Simplify Comparing Versions of Form, List, and Related List Layouts 
And also important in this context is the knowledge of how to correctly reset customized forms back to the OOTB state: https://support.servicenow.com/kb?id=kb_article_view&sysparm_article=KB0726207 
 
Screen Shot 2017-08-30 at 9.45.33 AM.png

 

 

Administration | Unknown Pages
As I mistyped in a hurry today, I accidentally came across the webpage "statsx.do", which left me amazed. First, this page is publicly available. Secondly, it is delivered superfast and I wonder how it was technically implemented. And third, it contains a lot of valuable information (e.g. number of available semaphores) that could be monitored automatically with an appropriate tool like Nagios. But I couldn't find any documentation on this. 
 
MaikSkoddow_0-1673082123382.png

 

 

Development | Phone Numbers
For the field type "E.164 Phone Number" there is also an undocoumented API GlideElementPhoneNumber which is used by the Script Include "PhoneNumberFormatter". This API can be used, for example, to determine the country associated with a phone number:
 
var objPhoneNumber     = new GlideElementPhoneNumber();
var isValidPhoneNumber = objPhoneNumber.setPhoneNumber( '+49 170 123456789', true);

gs.info(isValidPhoneNumber);
gs.info(objPhoneNumber.getTerritory());
 
MaikSkoddow_0-1672716351249.png

 

 

Administration | Unknown Tables
ServiceNow has a field type "E.164 Phone Number" which makes sure that all entered phone numbers follow the predefined local formats. Furthermore ServiceNow is able to preselect the related country automatically after a user has entered a phone number. To make this possible, there is a table sys_phone_territory in ServiceNow which contains the international area codes of all countries. And in the table sys_phone_validate all formattings of all phone numbers from all countries are stored.
 
 
MaikSkoddow_1-1672548777330.png

 

 

Subscription & License Management | Roles
In ServiceNow a leading practice is to let users inherit their roles from the groups they are member of instead of direct roles assignments. This gets especially important when it comes to subscription management, as you have to assign all user groups to your user-based subscription, which holds users with licensable roles. For this reason, I have extended an older article to include an instance scan check that scans for users who have direct assignments with licensable roles:
 
 
MaikSkoddow_0-1672547552499.png

 

Basics | Unknown Pages
You have impersonated a different user, but now you are trapped in any of the Service Portals? Open page /impersonate_dialog.do to impersonate back to your account.
 
MaikSkoddow_1-1672031619699.png

 

 

Administration | Maintenance & Performance
As an experienced administrator or developer, you probably take a look at the so-called node logs from time to time to identify the root cause of exotic problems. But be careful: Using the standard modules "Node Log File Browser" and "Node Log File Download" you will only get the logs of the node you are currently logged in to. But the problem could have occurred on another node. To get the logs from all nodes at once instead, you can go to the sys_cluster_state table and call "Download Logs from selected Nodes" in the list actions menu for the selected records.
 
MaikSkoddow_0-1672031213902.png

 

 

Administration | Maintenance & Performance
I know 3 different ways to determine the size of the used space for the database in a ServiceNow instance, but they all have a flavor of a workaround. A better approach is using the table ua_instance_state, which hosts one record that reflects the value on a daily basis.
 
MaikSkoddow_0-1670995277027.png

 

 

Administration | Maintenance & Performance
With the help of an additional and free plugin you can limit the number of concurrent interactive sessions for a specific user or role in ServiceNow! This means that if you limit all users to one concurrent session, and a user tries to log in using two different browsers (such as Chrome and IE or Chrome and Chrome incognito), they will be logged out of their previous session. 
 

 

 

ServiceNow Ecosystem | Customer Success Center
Recently, I came across an amazing collection of so-called reference architectures in ServiceNow's Customer Success Center. Instead of always thinking in silos, these documents illustrate which products and packages can be leveraged to gain maximum value based on business capabilities/stories. Very helpful for conversations with customers on that level.
 

 

 

Administration | SSO
Nowadays, all companies introducing ServiceNow wants to integrate at least the PROD instance with the existing corporate identity provider. For this reason, it is important for a ServiceNow admin or consultant to know how to set up and configure the SSO feature. Fortunately, you can practice this topic in your PDIs using the free SSOCirlce service. And on top of that, ServiceNow has provided a comprehensive guide that you just have to follow. 
 

 

 

ServiceNow Ecosystem | Now Learning Portal
In the Now Learning Portal, there is a treasure of insightful videos for each family release given by the ServiceNow product teams - the so-called "transfer of information" (TOI). Use the following link:
 

 

 

Development | Security
When developing ACL scripts it would be helpful to impersonate on script level instead of wasting time with impersonating for and back manually. And this is the code for it:
 
MaikSkoddow_0-1670742319919.png

 

 

ServiceNow Ecosystem | Search
Did you know that by using the seach at ServiceNow's main website www.servicenow.com you can kick off a one-search over the most important portals in the ServiceNow ecosystem? In the search results page you then can filter by search sources. And you even are provided here with search results to restricted content, so at least you know some content is there, but you need to login for accessing it.x.
 
MaikSkoddow_1-1668777967930.png

 

 

Next Experience UI
You know this: Clicking on the (i) icon right beside a reference field and then on "Open record" with pressed Ctrl key loads the referenced record in a new tab, but without the header/navigation bar. Uncool! But you can force loading the navigation bar with setting a "Display" preference:
 
MaikSkoddow_0-1668777837273.png

 

 

CMDB | Import
Far too often I see questions like "how to prevent duplicate CIs." And when I look at all the examples from ServiceNow where CIs are loaded into the CMDB using Excel files via normal Import Sets & Transform Maps, it's not surprising. Instead use an application that is prepared for a CMDB import, such as "IntegrationHub ETL". And if that is not possible, you should at least call the IRE directly in the Transform Map. See the example from the following documentation page.
 

 

 

Administration | Auditing
If you want to know what data has been exported fromServiceNow's list view, you have to go to the table sys_poll. But these data is cleared with the end of the user session. So if you want to report on this over a longer time period, you can deactivate a script action. For more information, read the following Knowledge Article.
 

 

 

Administration | Logging
I'm sure many of you already know that feature, but I just came across it and was happy not to have to download hundreds of megabytes of node log files all the time. So if you want to stream the node logs to your browser, use the URL /channel.do?sysparm_channel=logtail
 
MaikSkoddow_4-1668777198592.png

 

 

Development
OOTB the code search in your ServiceNow instance covers 31 tables only. If you want to search all available tables and script-related fields, you can execute in a "Scripts - Background" console my script available at GitHubYou can leverage the code search in Studio, with the UI Page "CodeSearchExampleUse" or via the browser extension "SN Utils"
 
MaikSkoddow_3-1668776951399.png

 

 

Next Experience UI
If you don't like the illustration on the login page of your ServiceNow instance, you can disable them via system property glide.ui.polaris.login.show_illustrations.
 
MaikSkoddow_1-1668776809085.png

 

 

Administration | User Management
If you need transparency on any user's role changes in ServiceNow (e.g. for any audit purposes) you can create a system property glide.role_management.v2.audit_roles with value "true". After that all changes are populated at table sys_audit_role.
 
MaikSkoddow_0-1668776641144.png

 

 

Next Experience UI | Banner Logo
I saw several Community questions on how to change the banner image (mostly the customer logo) in the Next Experience UI. And I also had some troubles with changing it, but the following approach solved it. Upload the image to the record of the system property glide.product.image.light and set its value as follows. Then clear the cache and log out / log in again.
 
2022-11-01 03_56_52-glide.product.image.light.png

 

 

UI | List View
One of my first ServiceNow tips on LinkedIn was about how to sort group counters with the help of a URL parameter. Now ServiceNow surprises us in the Tokyo release with a built-in UI option in the list view to achieve the same with two clicks::
 
MaikSkoddow_0-1666492248002.png

 

 

Now Learning
If you want to stay informed about the latest courses and their updates, you should regularly check the following page in the Now Learning portal: Content Releases
 
MaikSkoddow_6-1665154875942.png

 

 

Basics | Unknown Tables
There is a undocumented but interesting table sys_status with lots of interesting information like the used Java version. The number of records with the same name corresponds to the number of the underlying application nodes.
 
MaikSkoddow_4-1665154554350.png

 

 

Next Experience UI | Workspaces
If you don't want to offer all the Workspaces ServiceNow is providing or restrict the visibility of Workspaces to dedicated user groups, then you can create special ACLs explained in the following linked support KB article. The required ACLs for the Service Operation Workspace (id: sow) would be:

now.sow.*
now.sow.home
 

 

 

Next Experience UI | Global Text Search
If you have recently switched to the Next Experience design, you should definitely check the global text search, because its configuration is different and not automatically taken over from the previous U16 configuration.
 

 

 

Next Experience UI
Customizing the Next Experience UI is completely different much more expensive than in the UI16. If you just want to have a simple visual indicator to distinguish between the DEV, TEST and PROD environment, I recommend my article Change the header's background color in the Next Experience
 
MaikSkoddow_3-1665154048575.png

 

 

ServiceNow Ecosystem | Corporate Website
Do you also sometimes find it difficult to locate something on the ServiceNow website? Then you might find the following (hidden) sitemap useful:
 

 

 

Dashboards
You have a nice & valuable dashboard you want to present on a wall mounted display in your office? Get the dashboard URL and add the parameter &sysparm_header=hidden
Then install a browser extension for automatic reloading the dashboard page and activate the full screen mode.

 

 

Basics | Queries
Sometimes crucial ServiceNow records (e.g. Users, Groups) have to be deleted (e.g. due to any regulations) or were deleted accidentally, although other tables are referencing them (e.g. field "Assignment Group" of task table). This results in so-called "broken" references. With the help of a special filter condition, you can filter them:

<FIELD> is not empty AND <FIELD.SysID> is empty
 
MaikSkoddow_2-1665153375869.png

 

 

Basics | XML Export/Import
Moving foundation data from one instance to another can be rather time-consuming, as many XML files (one for each table) have to be imported in the target instance manually. But you can save time by merging all XML files into a single one. Just copy all branches (tag name = table name) of the 2nd level below the root tag <unload>.
 
MaikSkoddow_0-1665153046823.png

 

 

Basics | UI Actions | Unknown Tables
Each main product in like ITSM, CSM or FSM is shipped with a bunch of UI Actions and not all of them are always required. But instead of deactivating them or changing their conditions (and thus risking a skipped record in the next upgrade), you can use the embedded list "Requires roles" (table sys_ui_action_role). This way you don't change anything in the original record, and also can limit the visibility elegantly.
 
MaikSkoddow_1-1665153187135.png

 

 

Basics | Dictionary
I accidentally stumbled upon an interesting ServiceNow feature that is very useful if you deal a lot with JSON-based payloads. With the help of the field-related dictionary attribute json_view=true you can enable a JSON viewer which outputs the payload in a readable way.
 
MaikSkoddow_12-1665152558189.png

 

 

Basics | Navigation | Unknown Tables
Have you ever wondered why when you open a record from the sys_hub_flow table, the Flow Designer is started? The reason is a corresponding navigation handler (table sys_navigator). You can also define your own navigation handler here, for example to ensure that a workspace for your custom table is always opened instead of the standard form view.

 

 

Implementation | Flow Designer
The number of your Flows is growing rapidly and you no longer know exactly which business logic was implemented where? While a search via my favourite table sys_metadata does not help here, you may find what you are looking for in the "Payload" field from the sys_update_xml table. Reason: For transferring Flows to another instances they are serialized completely to a readable version.

MaikSkoddow_11-1665152385504.jpeg

 

 

Development | Email Notifications | Unknown APIs
If you want to extract the watermark of an email you can use the following API method
 
GlideEmailWatermark().parseMessageNumber(<EMAIL BODY TEXT>);

MaikSkoddow_10-1665152315022.png

 

 

Development | Unknown APIs
There is a global API ChoiceList() (unfortunately not invokeable from scoped apps) for dealing with choice list values.  With its help you can translate choice labels to values and vice versa.

MaikSkoddow_9-1665152277891.png

 

 

Security | ACLs

If you want to debug your ACLs and only see ACL log statements which are related to refusing access to user, you can invoke from "Scripts - Background":

 

GlideSessionDebug.enable("security_refuse");

 

The same you can do if you want to see only ACL log statements which are related to granting access to user:

 

GlideSessionDebug.enable("security_grant");

 

if transactions are running in background, you can print ACL logs to node log file by:

 

GlideSessionDebug.enable("security_refuse, true");
GlideSessionDebug.enable("security_grant, true");

 

 

Security | Passwords
If you want to make sure that your ServiceNow users do not reuse a password they have already used during in the past, you can follow these instructions to configure it accordingly:

> Prevent users from re-using recently used passwords on the Password Reset screen

 

 

Basics | First Aid
Due to a JavaScript error in a global UI Script I created, I could no longer log into my instance. After my heart started beating again, I feverishly searched for a solution. Deactivating the UI Script via table API fails because of the configured MFA. Fortunately, the browser plugin "Adblock Plus" offers the option to block the loading of individual files.

MaikSkoddow_6-1665151573619.png

 

 

Customer Service Managemenr | Security
I know that not all customers are happy with the fact that additional records (e.g. Incidents or Catalog Requests) are created from a CSM case, but are not visible to the requester. For this reason, ServiceNow has published a document describing how to grant read access to these records to external users by modifying the ACLs. You can download it from the Now Create portal.

> ITSM Entities: Giving External View Permission in CSM

 

 

Development | Unknown APIs
With the function
 
GlideTransaction.get().getRequest().getRequestURL()
 
you can retrieve the current ServiceNow URL in a server-side script. That way you have a chance to identify in which experience (backoffice, workspace, service portal, etc.) the user is. Useful for example in UI Actions.

 

 

Security | Activity Stream | Unknown Tables
What I love about ServiceNow is that every time I think I know everything about a topic, I come across an unknown fact. For example, I didn't realize that the visibility of emails in the activity stream is also controlled by the email_access_restriction table.

> Control visibility to email records generated by notifications

 

 

Imploementation | Flow Designer | Inbound Email Trigger
I was suprised to see that OOTB you can only have one inbound email Flow in ServiceNow. However, if you need more than one (for example, for different tables), you need to set the system property glide.hub.flow.inbound_email_trigger.show_advanced to "true". 

> Allow multiple triggers to process an inbound email

 

 

Capability Map
During the CTA training, we talked a lot about ServiceNow's capability map, and I was already asked where to get a PPT version for usage in the own presentations. Those who do not have access to the Partner Portal can download it from the Now Create Portal: ServiceNow Capability Map
 
MaikSkoddow_0-1665303105620.png

 

 

Security | ISC
Since the San Diego release, the important but hardly noticed Instance Security Center (ISC) is not an integral part of the baseline installation any longer but an individual store app.

> Instance Security Center

 

 

Implementation | Flow Designer
If you want to be able to select sys_* tables at Flow Designer, I want to provide the right answer: You have to extend the System Property glide.ui.permitted_tables by the respective table names

> KB0852462

 

 

Administration | Database
If you want to add a new column to a table within CMDB which already has many millions of CIs, you should do this via the Form Designer. The difference to approaches like Class Manager or Dictionary is that the Form Designer performs the changes in the background, and you can observe the progress. In addition, your session is not blocked, which allows you to continue working in parallel.

MaikSkoddow_5-1665151323591.png

 

 

Development | Unknown APIs
In high performance scenarios where the load is distributed across multiple application nodes, it might be important to know on which node exactly the log output was written. For this, you can use the following function which will return the node ID:
 
GlideServlet.getSystemID();

 

 

Administration | View Rules
View Rules are driving me crazy. Articles KB0686741 and KB0719228 explain, why they not really work. But fortunately there is a system property glide.ui.remember_view you have to set to "false". After that, they work like a charm.

 

 

Development | APIs
If you need the user's IP address - for example for any kind of validations - you can leverage the following server-side API invocation (also see KB0861180)
 
GlideTransaction.get().getRemoteAddr()

 

 

Next Experience UI
Nice gimmick: By using the URL parameter sysparm_use_polaris=false you can combine the header bar of the "Next Experience" (Polaris) with UI16 content.
 
MaikSkoddow_4-1665151014702.png

 

 

Basics | Implementation
For the delicate topic "Customization vs. Configuration" there is a public Support Article (KB0553407). However, by chance I came across another protected Support Article that discusses this topic in more detail. As this article is only reachable after login at the support portal, I have attached it here
 

 

 

Administration | Maintenance & Monitoring | Unknown Tables
If you want to monitor the health of your ServiceNow instance, you should regularly check the table diagnostic_event and configure an email notification for inserted records with "Severity" = "Error".
 
MaikSkoddow_7-1665152159843.png

 

 

Development | Data Security
Sometimes it is necessary to generate masses of artificial data that make no sense but are necessary for testing. Here the following API method can help, which expects the length of the string to be generated as the only parameter.

MaikSkoddow_3-1665148728068.png

 

 

Customer Service Managment
There was an interesting Community question on how to get all cases for all accounts of the same hierarchy (for example "Boxeo" & all of it's subsidiaries). The solution is using the "Account Path" field of the "Account" table. As it is a String field, you can look up there with a "starts with" operator and the "Account Path" of the parent Account:
 
MaikSkoddow_2-1665148399234.png

 

 

Integration Hub | Unknown Tables
You want to know how many transactions via the Integration Hub have been performed?
Go to Dashboard "IntegrationHub usage" or open table ua_ih_usage.

MaikSkoddow_1-1665148274812.png

 

 

Development | Unknown APIs
You want to verify whether a table exists with just a one-liner?
Use one of these two methods:

new GlideRecord('incident').isValid();

gs.tableExists("incident");

 

 

Administration
I find it exciting that I can discover something new in the ServiceNow universe every day. Recently I came across the snc_read_only role which, along with other roles (e.g. admin or itil, provides some interesting cases to address.

 

 

Development | APIs

A simple and undocumented timezone converter in server-side scripts:

 

var strConvertedDateTime = 
  new GlideScheduleDateTime("2022-03-03 06:30:00").convertTimeZone("CET", "IST");


var gdtConvertedDateTime = new GlideDateTime(strConvertedDateTime);


gs.info(gdtConvertedDateTime);

 

 

MID Server
I really like the MID Server, but articles like the following should make you realize why it is a terrible idea to run MID servers for PROD and Non-PROD in parallel on the same host!
 

 

 

Administration
The following support article helped me to really understand the difference between "table per hierarchy" and "table per class" model. And also interesting to me is the automatic model switch when task table has more than 1 million record.
 

 

 

Development | Unknown APIs
If you want to check in a condition field whether a table field exists, you can use the isValidField() function of the GlideRecord API:

new GlideRecord('incident').isValidField('number')

 

 

Development
Maybe you already know this, but you can reduce a Script Include to just one method. And if the method name is the same as the Script Include, you can call it without the new operator:

getValue();
 
instead of
 
new ScriptIncludeName().getValue();

MaikSkoddow_0-1665147868948.png

 

 

Dashboards | Interactive Filters
You want to know in which Dashboards your Interactive Filters are used?
Open Interactive Filter record, "Launch Dependency Assessment" and then select "Show used by" option for the respective tile on the Assessment Board:

MaikSkoddow_5-1665147299964.png

 

 

Next Experience UI
Did you notice all the new indicators when impersonating a user in San Diego's New Experience?
  • Red bar at the top
  • Red circle around the avatar image
  • Eye icon in the upper right corner of the avatar image
  • Hint "Impersonating User"

 

MaikSkoddow_4-1665147195713.png

 

 

Development | Unknown APIs
You want to annoy your colleagues? Then execute the following code line in a background script console from time to time:
 
GlideSessions.lockOutSessionsInAllNodes('<USER NAME>')

 

 

Subscription & License Management | Custom Tables
As I come across questions regarding custom tables from time to time, I want to provide an extracted Knowledge Article from the Support Portal. This article is quite detailed and should answer all questions.

> KB0997373

 

 

Basics | Unknown Tables
If you ever wanted to know where your ServiceNow favorites are stored, go to table sys_ui_bookmark. And be careful: as this table is not audited OOTB, a deleted favorite is gone forever!

 

 

Development
Would you like to have a kind of "Save as Draft" button without the need to fill out mandatory fields?
Enter "sysverb_cancel" at UI Action field "Action name". And the following screenshot reveals another trick:

 current.update();
 
can also create new records!

MaikSkoddow_3-1665146938110.png

 

 

Basics | Unknown Tables
Would you like to know by which record producer your record (e.g. Incident) has been created?
Go to table sc_item_produced_record.

 

 

Email
Do you also find it annoying that in email notifications, all recipients are listed in the TO field and thus are visible to each other?
Set the system property glide.email.smtp.max_recipients to "1" and for each recipient an individual email will be created.
But keep in mind, that this is a system-wide setting which applies to all notifications!

 

 

Basics
You are entering a ServiceNow project, and you'd to know when the customer instance that has been running for years was originally provisioned?
Check creation data of system property instance_name.

 

 

Subscription & License Management | Unknown Tables
For your ServiceNow license optimization, you want to know which user has accessed which application?
Go to table ua_app_usage and start building reports. Interesting columns: "Access Count" & "Fulfillment Count":

MaikSkoddow_2-1665146750891.png

 

 

Subscription & License Management | Unknown Tables
You want to know whether a ServiceNow role is licensed or not?
Go to table license_role and check column "Role Type". Pretty much everything except "Requester" consumes any kind of license.

MaikSkoddow_1-1665146639878.png

 

 

Development | Unknown APIs
Do you already know the undocumented ServiceNow API GlideStopWatch? With it, you can easily measure the execution time of code running on the server side.

MaikSkoddow_0-1665146550642.png

 

 

Inspiration
If you need some inspiration about what's possible in ServiceNow, you should check out that Innovations Portal:

> ServiceNow Innovations

 

 

Basics | Unknown Tables
Looking for a way to search fully and truly across all configuration data in ServiceNow?
Run a keyword search in the sys_metadata table and additional consider using wildcards (also see KB0692729)

MaikSkoddow_2-1665130219758.png

 

 

Basics
You have a ServiceNow Sys ID but don't know which table it belongs to? Try out my widget that will find the respective table.

> Open record page by Sys ID

 

 

Administration
You want to know which users are logged in to your ServiceNow instance?
Don't go to the "Logged in users" module, as this displays users for your current node only.
Instead, search at table sys_user_session for "name != null AND invalidated=NULL".

 

 

Administration

You would like to know how much space the database in your ServiceNow instance has? Enter the following command in the Scripts console:

gs.info(
  SNC.UsageAnalyticsScriptUtils.getCount(
    'Primary DB size (MB)',
    'Primary DB size of this instance (in MB)'
  )
);

 

 

Agent Workspace
You have missed the possibility to edit cells inline in the list view of the ServiceNow Agent Workspace like in UI16?
Set property glide.lists.inline_editing_enabled to "true".

 

 

UI | List view
Opening a table with several million entries takes too long?
Add URL parameter "sysparm_filter_only=true" to stop initial load. Define now your filter to narrow down the results. The same can be achieved by entering a table name, a dot and "filter" into the application navigator, for example incident.filter

 

 

Development | Unknown APIs

In the Community users often ask how to remove the tags from HTML content. And that's the (undocumented) answer:

new GlideSPScriptable().stripHTML(yourHtmlStr);

 

 

Service Portal
You want to offer your Service Portal to end users (not logged-in!) in a different language (let's say German) than your system language (hopefully English) is?
Then set the field preferred_language of the guest user to that language.
 
MaikSkoddow_8-1665152200024.jpeg

 

 

Basics
Fun fact: The Sys ID of the "Default view" record at ServiceNow table sys_ui_view is not the well-known 32-characters long text but "Default view":

MaikSkoddow_1-1665129121788.jpeg

 

 

UI | List View
Did you know that it is possible to sort a grouped list view by the number of rows per group in your ServiceNow instance? Just append one of the two parameters to the URL:

&sysparm_group_sort=COUNT
&sysparm_group_sort=COUNTDESC

MaikSkoddow_0-1665128962901.jpeg

 

 

Mobile
Have you ever been annoyed by being redirected to the mobile web UI when accessing your ServiceNow instance with a mobile device? If this is the case, you should clear the following three properties, and you will be offered the desktop version on your mobile browser:

glide.ui.m_agents
glide.ui.mobile_agents
glide.ui.tablet_agents

 

 

Source Control
After answering the same question several times in the Community now, I would like to point out that since 13.08.21 basic authentication (username + password) is no longer supported in GitHub. Instead, a personal access token has to be created and used. Currently, the use of basic authentication unfortunately leads to the situation that the users who want to fork a GitHub repository in the Developer Portal for the exercises, get "strange" error messages in the ServiceNow Studio.

 

 

Service Portals
Good to know: ServiceNow will continue to support AngularJS in the future!

 

Comments
Lucas Vieites
ServiceNow Employee
ServiceNow Employee

This is a fantastic list of tips and tricks. I have bookmarked it for future use. Thank you.

By the way, there's no need to use the  &sysparm_group_sort parameter anymore in Tokyo. This functionality has been added to the list view:

list_sort_by_count.png

The arrow icon will show up once you group by any of the visible headers.

 

Maik Skoddow
Tera Patron
Tera Patron

Hi @Lucas Vieites 

thanks for the tip and I already have provided it on LinkedIn (https://www.linkedin.com/posts/maik-skoddow_servicenow-activity-6982302867248275456-fIwb?utm_source=... ) 

The problem with the new community is the limitation of 60000 characters for an article and thus I cannot extend it anymore.

If that limitation is not is increased, I have to create another article 😞

Lucas Vieites
ServiceNow Employee
ServiceNow Employee

That's actually where I saw it first, and commented on it! It just didn't register that you were the same person.

lbrown3
Tera Explorer

Fantastic list, really appreciate the time to put this together!

Prasant Kumar S
Tera Contributor

Helpful content.

Franck Jaffre
ServiceNow Employee
ServiceNow Employee

Fantastic list, yes !!

Bookmarked

Gary King
Tera Explorer

Appreciate the updates, this is so helpful!

KKrabbenhoft
Tera Expert

Fantastic! I have also bookmarked this and shared it with my DEV team Kudos to you sir!!

Fuki
Tera Contributor

super welldone , i love this 

senon
Tera Expert

@Maik Skoddow 

very impressive. I have favorited this!

As for the question, I'm having trouble running the script below.

 

gs.info(
  SNC.UsageAnalyticsScriptUtils.getCount(
    'Primary DB size (MB)', 
    'Primary DB size of this instance (in MB)'
  )
);

 


Output is "*** Script: 0"

 

I'm looking for a code that defines "SNC.UsageAnalyticsScriptUtils.getCount" to find the cause, but I can't find it.

 

Where is the script where this code is defined?
Also, any ideas what might be causing this output result?

Saiganeshraja
Tera Guru
Tera Guru

Nice Article 🙂  I, Really Impressed by the way it was presented.

courtenay1
Tera Expert

"Fun fact: The Sys ID of the "Default view" record at ServiceNow table sys_ui_view is not the well-known 32-characters long text but "Default view" 

... more fun: There are actually ~800 sys IDs in the system which are not 32 hex chars - 700 or so in the "Design System Icons" table, Many of the other 100 are in constant use; tables ACL Operations and Types, Numbers etc. Some have been in the system pre-Aspen, others recently.

The CI Relationship Types table did have the sys IDs of "1" and "2" but they were silently updated to 32 hex around Geneva from memory. They were survivors from the first release of pre-ServiceNow GlideSoft. They were the foundation records - to record an incident against a CI you need a CMDB. CIs related together by type created a CMDB.

sebastian_g_snc
ServiceNow Employee
ServiceNow Employee

Thank you, for this fantastic list !

MorriX1
Tera Contributor

Amazing. 

Thank you for taking the time to put this together.

-O-
Kilo Patron
Kilo Patron

The link for tile "Next Experience UI | Global Text Search" is faulty: it contains the HTML entity instead of the ampersand (&amp; vs. &).

Hagos
Tera Contributor

Fantastic! I have bookmarked this.

Kudos to you sir!!

Nancy Haig
Tera Explorer

Great list - I have bookmarked it as well.

 

Thank you!

cynlink1
Tera Expert

@Maik Skoddow - Wonderful collection of information. Thank you for sharing!

 

I have a question related to the 'Subscription & License Management | Roles' section. I know the leading practice is to let users inherit their roles from the groups they are member of instead of direct roles assignments. However, knowledge base owners and managers are automatically assigned a knowledge role directly by the system (ServiceNow). When I implemented the ' Prevent direct assignment of licensable roles to users', it interfered with the role assignment during the creation of a new knowledge bases. Did you encounter this problem? If yes, how did you work around it?

 

Closely related question - I attempted to create scripts that will automatically add/remove the KB owners and managers to/from a group so I could associate a subscription to the group to account for the subscription allocations. I was able to get the script working that adds users to the group when a knowledge base is created or updated, but I am struggling with the script to remove the users from the group when they are no longer a KB owner or manager.  

 

If anyone sees the problem, please let me know how to fix it. Many thanks!

 

Business rule - Remove owner from LIC group 

Table - kb_knowledge_base

When - after Insert & Update

Filter condition - Owner changes

 

(function executeRule(current, previous /*null when async*/ ) {
var ownUsrid = previous.owner.user_name;
var memGr = new GlideRecord('sys_user_grmember');
memGr.initialize();
memGr.addQuery('group', 'ca791aabdb17201036d8af6d139619e4'); // the sys_id of the LIC_USR_SET-Knowledge group
memGr.addQuery('user', previous.owner);
memGr.query();
if (memGr.next()) {
memGr.deleteRecord();
}
//gs.info('Removing '+previous.owner+ 'from LIC_USR_SET-Knowledge group sys_id ca791aabdb17201036d8af6d139619e4');

})(current, previous);

Amy Zaretsky1
Tera Contributor

Hi,

this link doesnt work. Is this on how to add documentation link to help pages within servicenow for licensed users? 

 

 

Documentation
In case you did not know this little trick yet ...
Maik Skoddow
Tera Patron
Tera Patron

Hi @Amy Zaretsky1 

Thank you for the hint! It seems that the linked artcle wasn't migrated from the old community portal to the new one last year and thus is now lost. But I added a respectice tip at the top so I don't need to rewrite it.

Roberto P
Tera Contributor

Thank your for sharing your list.  I hope more will share within this community (like this) in making this community more interactive with each other.  I've met so many knowledgeable people, who actually care about providing the best functions and support for their customers.  Thanks again!  Bookmarked!

Version history
Last update:
‎01-26-2024 09:08 PM
Updated by:
Contributors