Blog

Anonymous Incident Creation

Create a public page for users to submit incidents without logging in.

Please note, check on ServiceNow licensing before utilizing this. Licensing does change, and it may not be valid with your current agreement.

Anonymous Incident Form

Thank You Page

Code

Widgets

  1. Get a reCaptcha Key at: https://www.google.com/recaptcha/admin

  2. If you want to use a user like Anonymous User as the caller if email doesn’t match, substitute your sys_id for that caller.

  3. Widgets need to be public to work

Anonymous Incident Creation

Name: Anonymous Incident Creation
Public: true

Body HTML Template

<script src='https://www.google.com/recaptcha/api.js'></script>
<div class="panel panel-{{options.color}} b">
  <div class="panel-heading" >
    <h4 class="panel-title" style="cursor: default">
      <span ng-if="c.options.glyph">
        <fa name="{{::c.options.glyph}}" />
      </span>{{c.options.title}}</h4>
  </div>
  <div class="panel-body">
    <form ng-submit="c.checkCap()">
      <div class="vsplit col-sm-6">
        <fieldset class="form-group ng-scope ng-isolate-scope">
          <label><span title="Mandatory" class="fa fa-asterisk mandatory" ng-class="{'mandatory-filled': field.mandatory_filled()}" aria-hidden="false"></span>${First name}</label>
          <input ng-required="true" ng-model="data.first_name" class="form-control" type="text" maxlength="50" autocomplete="off" ng-readonly=data.setReadonly />
        </fieldset>
        <fieldset class="form-group ng-scope ng-isolate-scope">
          <label>${Middle name}</label>
          <input ng-model="data.u_middle_name" class="form-control" type="text" maxlength="50" autocomplete="off" ng-readonly=data.setReadonly />
        </fieldset>
        <fieldset class="form-group ng-scope ng-isolate-scope">
          <label><span title="Mandatory" class="fa fa-asterisk mandatory" ng-class="{'mandatory-filled': field.mandatory_filled()}" aria-hidden="false"></span>${Last name}</label>
          <input ng-required="true" ng-model="data.last_name" class="form-control" type="text" maxlength="50" autocomplete="off" ng-readonly=data.setReadonly />
        </fieldset>
      </div>
      <div class="vsplit col-sm-6">
        <fieldset class="form-group ng-scope ng-isolate-scope">
          <label><span title="Mandatory" class="fa fa-asterisk mandatory" ng-class="{'mandatory-filled': field.mandatory_filled()}" aria-hidden="false"></span>${Email}</label>
          <input ng-required="true" ng-model="data.email" class="form-control" type="email" maxlength="200" autocomplete="off" ng-readonly=data.setReadonly />
        </fieldset>
        <fieldset class="form-group ng-scope ng-isolate-scope">
          <label><span  title="Mandatory" class="fa fa-asterisk mandatory" ng-class="{'mandatory-filled': field.mandatory_filled()}" aria-hidden="false"></span>${Phone Number}</label>
          <input ng-required="true" ng-model="data.u_phone" class="form-control" type="text" maxlength="50" autocomplete="off" ng-readonly=data.setReadonly />
        </fieldset>
      </div>
      <div class="col-sm-12">
        <fieldset class="form-group ng-scope ng-isolate-scope">
          <label><span title="Mandatory" class="fa fa-asterisk mandatory" ng-class="{'mandatory-filled': field.mandatory_filled()}" aria-hidden="false"></span>${Short description}</label>
          <input ng-required="true" ng-model="data.short_description" class="form-control" type="text" maxlength="160" autocomplete="off" ng-readonly=data.setReadonly />
        </fieldset>
        <fieldset class="form-group ng-scope ng-isolate-scope">
          <label><span title="Mandatory" class="fa fa-asterisk mandatory" ng-class="{'mandatory-filled': field.mandatory_filled()}" aria-hidden="false"></span>${Description}</label>
          <textarea ng-required="true" ng-model="data.description" class="form-control" type="text" maxlength="4000" autocomplete="off" ng-readonly=data.setReadonly></textarea>
        </fieldset>
        <div class="g-recaptcha" style="margin-bottom:12px;" data-sitekey="{{data.sitekey}}"></div>
        <input class="btn btn-primary" type="submit" value="Submit" />
      </div>
    </form>
  </div>
</div>

CSS

.fa-asterisk {
  padding-right: .25em;
}

Server Script

(function() {
	//Substitute your Recaptca Key here
        data.sitekey = '';
	if (input && checkPhoneNumber()) {
		data.formData = 'Created from Anonymous Incident Creation:'+'\n';
		data.formData += 'First name: '+ input.first_name+'\n';
		var fullName = input.first_name+" "+input.last_name;
		if (input.middle_name != '' && input.middle_name != undefined) {
			data.formData += 'Middle name: '+ input.middle_name+'\n';
			fullName = input.first_name+" "+input.middle_name+" "+input.last_name;
		}
		data.formData += 'Last name: '+ input.last_name+'\n';
		data.formData += 'Email: '+ input.email+'\n';
		data.formData += 'Phone: '+ input.u_phone+'\n';
		data.formData += 'Short description: '+ input.short_description+'\n';
		data.formData += 'Description: '+ input.description+'\n';
		data.table = "incident";

		gr = new GlideRecord(data.table);
		//Match Caller
		var grUser = new GlideRecord('sys_user');
		grUser.addQuery('email', input.email);
		grUser.query();
		if(grUser.next()){
			gr.setValue('caller_id', grUser.sys_id);
		}
		else {
			//Set to caller of your choice here
			gr.setValue('caller_id', '10fb0f3ddbc323007212722ebf96193e');
		}
		gr.setValue('short_description', input.short_description);
		gr.setValue('description', input.description);
		gr.setValue('contact_type', 'self-service');

		gr.work_notes = data.formData;
		var myRecord = gr.insert();
		//gs.addInfoMessage('Thank you! We will get back to you shortly. You can close this window.');
		data.setReadonly = "true";
	}

	function checkPhoneNumber() {
		var pattern = /^\s*(?:\+?(\d{1,3}))?[-. (]*(\d{3})[-. )]*(\d{3})[-. ]*(\d{4})(?: *x(\d+))?\s*$/;
		if(!pattern.test(input.u_phone)){
			gs.addErrorMessage('Phone enter a valid Phone Number: (999) 999-9999, 999-999-9999, 999-999-9999 x9999');
			return false;
		}
		else {
			return true;
		}
	}
})();

Client Script

function() {
	var c = this;
	c.checkCap = function() {
		c.data.captchaSession = grecaptcha.getResponse();
		if (!c.data.captchaSession) {
			alert('Nice try, robot.');
		}
		grecaptcha.reset();
		if (c.data.captchaSession) {
			c.server.update();
			document.location = "/sp?id=anon_incident_ty";
		}
	}
}

Fields: Title, Bootstrap color

Anonymous Incident Creation - Thank You

Name: Anonymous Incident Creation - Thank You
Public: true
Body HTML Template

<div class="panel panel-{{options.color}} b">
  <div class="panel-heading" >
    <h4 class="panel-title" style="cursor: default">
      <span ng-if="c.options.glyph">
        <fa name="{{::c.options.glyph}}" />
      </span>{{c.options.title}}</h4>
  </div>
  <div class="panel-body">
     <h1 style="text-align: center;margin:100px 0px 100px 0px;">{{c.options.thank_you_message}}</h1>
  </div>
</div>

Fields: Bootstrap color, Glyph, Title
Option Schema: [{"name":"thank_you_message","section":"other","label":"Thank You Message","type":"string"}]

Pages

Please note that pages need to be public to work.

Anonymous Incident Creation

Title: Anonymous Incident Creation
ID: anon_incident_creation
Public: true
Page Designer: 
1. Add a Container and 12 Block.  
2. Drop “Anonymous Incident Creation” Widget in 12 block.  
3. Add Title to Widget: Report an Incident, Bootstrap Color: Primary

Anonymous Incident Creation - Thank You

Title: Anonymous Incident Creation - Thank You
ID: anon_incident_ty
Public: true
Page Designer: 
1. Add a Container and 12 Block.  
2. Drop “Anonymous Incident Creation - Thank You” Widget in 12 block.  
3. Add Title to Widget: Thank You!, Thank You Message: Thanks for submitting your incident. We will get back to you soon!, Bootstrap Color: Primary

TEST

Try out the new public page at

https://instance.service-now.com/sp?id=anon_incident_creation

Substitute “instance” with your ServiceNow instance name.