Javascript Creating Audit Record

Hi Everyone,
We have a requirement to start tracking what pages are being visited by the various users.  To that end we created a simple object with two fields.  PageName__c and URI__c.  I wanted to create a static resource that we can just add to the page when we want to audit, and this could capture the URI.

So we build the code, and it does insert a record, but the fields are not getting populated with any data and I am at a loss.   The user has rights since we can open the Audit table and edit the fields, so I don’t believe we have a security issue. 

Any insights are greatly appreciated!

((function(skuid) {
skuid.$(document.body).one(‘pageload’,function(){

//set initial variables
var currentLocation = window.location.href, curModel;

//check if the model already exists and so do not create it again
if(skuid.model.getModel(‘LOISAuditLog’)==‘undefined’|| skuid.model.getModel(‘LOISAuditLog’)==null)
{
console.log(“Creating LOISAuditLog Model”);

curModel = new skuid.model.Model();
curModel.objectName = ‘System_Audit_Log__c’;
curModel.id = ‘LOISAuditLog’;
curModel.recordsLimit = 1;
curModel.fields = [
{ id: ‘URI__c’ },
{ id: ‘PageName__c’}
];
curModel.initialize().register();
}
else
{
//Model exists, so just set the curModel to the existing one for the page load
console.log(“Audit Log Model Already Exists”);
curModel = skuid.model.getModel(‘LOISAuditLog’);
}

// Insert the new record into the Audit Table
curModel.createRow();
curModel.updateRow(curModel.getFirstRow(),{URI__c:currentLocation});

// Save the record
curModel.save({callback: function(result){
if (result.totalsuccess) {
console.log(‘Audit Log Entry Created’);
console.log(curModel.getFirstRow());
} else {
console.log(‘There was an error saving the Audit Record’);
console.log(result.insertResults);
console.log(result.updateResults);
console.log(result.deleteResults);
}
}});

});
}))(skuid);

I believe you’d be able to handle your use case with a declarative approach without going to code.

We’re doing something similar with an audit log of about 20 fields that gives us insight into a variety of usability and traceability insights. Our use case is a bit more advanced because we have a single page app and our navigation process manages browser state history, rewriting the URL into a short URL structure, pulling browser variables like viewport, page load time, memory consumption, etc. as well as dropping all of this information into an audit table. We had to go to Javascript to get all this done, but if you just need to capture the page name and a few other details, this could be done declaratively and you can use an Action Sequence that triggers off the page load to insert a record into your audit table.

This document has a lot of good variables you can use for tracking purposes:

https://docs.skuid.com/latest/v2/en/skuid/merge-syntax/global-merge-variables.html

The {{$Page.Name}} will give you the skuid page and the {{$Param.}} variable will give you variables in your url string. This is pretty handy when you want to keep track of the specific record that was visited, as an example. {{$Site.CurrentSiteUrl}} will give you the base URL if you need that.

Where we’re getting the most insight is from pulling the Salesforce object AuthSession, where you can pull down a ton of data like source IP, Location, Browser, and a bunch of other data that you can copy into your audit table.

Also to circle back on your desire for re-usability, you could set this up once and then use it as a page include. 

If you’re using V2, page includes are “sandboxed” from other page elements, so you may need to pass the parameters into the include with the query string rather than leveraging the global variables.  Not sure on that last bit.

Thanks John,

We have about 700+ pages, so the idea would be to add the static resource to the pages we want to monitor and let it be data loading be dynamic and managed from the single source so we wouldn’t need to touch the pages again. 

I did mess around with the Merge Variables, and I couldn’t get them to populate within Lightning and 12.1.5.  

Currently my workaround has been to create a Skuid page that has one model (the same one above), and then I embed that same static resource and it all works. 

So it would appear the problem I am having is the Object isn’t fully available for inserting the fields from the call.  Yet, once the fields are declared as a skuid model on the page, the exact same code functions just fine.

This is the starting point for us, I expect the details for what we want to audit to grow a lot and event potentially call other rest services for tracking, so I really would prefer just to include the single static resource and not have to create the overhead of a separate page include.

Based on your comment here, it looks like you’ll need to have the skuid model defined wherever you want to have this audit insert, which is why I suggest a page include so you don’t have to redefine it over and over.  With the include you just setup your model once in a central page and then drop the include on whatever pages you want to audit. 

Another approach might be to dynamically build the model, which you can add to your script.  Skuid has a tutorial on this approach here - https://docs.skuid.com/latest/en/skuid/javascript/dynamic-model-component-creation.html

A third alternative if you want to keep it all in a central Javascript resource would be to use an AJAX call to insert the record directly to Salesforce and bypass the Skuid model dependency altogether.

Regardless of how you manage the audit component, you’ll need to add a component to any pages you want to track, be it a javascript resource, a page include or adding models directly to your page.  We have about 1000 pages, but we’re wrapping all these in a single page app and execute our auditing from the wrapper page so it minimizes what we need to configure on each page.

Thanks John! 

I was using the Dynamic Model Creation which was why I was confused.  It was working, but wouldn’t save one of the field changes.  The record was created, but didn’t accept any of the field updates.  When viewing the object in the browser, the record was updated and did show the changed fields, but they never committed back to Salesforce when the save was executed (the code I pasted above).

Ultimately, I did end up with a Page Include to address the gap with a little javascript snippet on that page to grab the elements that are not available within the Global Merge Variables. 

Thanks again or all the suggestions