Skip to content

Instantly share code, notes, and snippets.

@dcinzona
Created April 22, 2022 16:29
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dcinzona/381f9caadd86d6560e6b88699f945759 to your computer and use it in GitHub Desktop.
Save dcinzona/381f9caadd86d6560e6b88699f945759 to your computer and use it in GitHub Desktop.
Visualforce Page Metrics
<!--
- Created by gtandeciarz on 6/21/17.
-->
<apex:page id="VisualForcePageUsage"
title="VisualForce Page Metrics"
readOnly="true"
standardStylesheets="false"
>
<!--
standardStylesheets="false"
applyHtmlTag="false"
applyBodyTag="false"
showHeader="false"
-->
<apex:slds />
<script type="text/javascript">
var __sfdcSessionId = '{!GETSESSIONID()}';
function inLightningExperience() {
var userTheme = '{!$User.UITheme}';
return ['Theme4d', 'Theme4u'].indexOf('{!$User.UIThemeDisplayed}') > -1;
}
</script>
<script src="/soap/ajax/40.0/connection.js"
type="text/javascript"></script>
<script type="text/javascript">
var config={
pages : [],
sortKey : 'Views',
sortOrder : 'desc',
since : 'LAST_WEEK'
};
var sortClass = 'slds-is-sorted';
function sortedDirClass() {
return sortClass + '_' + config.sortOrder;
}
function getMetrics()
{
config.pages = [];
var metricsById = {};
var whereClause = config.since == 'All Time' ? '' : `WHERE MetricsDate >= ${config.since}`;
var query = `SELECT ApexPageId, ApexPage.Name, SUM(DailyPageViewCount) FROM VisualforceAccessMetrics ${whereClause} group by ApexPageId, ApexPage.Name ORDER BY SUM(DailyPageViewCount) DESC`;
var result = sforce.connection.query(query);
var it = new sforce.QueryResultIterator(result);
while(it.hasNext()) {
var record = it.next();
metricsById[record.Name] = record.expr0;
console.log('Got record ' + JSON.stringify(record, null, 4));
}
var allPages = sforce.connection.query("Select Id, Name, CreatedDate, LastModifiedDate, LastModifiedBy.Name, LastModifiedBy.Id from ApexPage order by Name desc");
var pageIt = new sforce.QueryResultIterator(allPages);
while(pageIt.hasNext()) {
var record = pageIt.next();
var ct = metricsById[record.Name] != undefined ? metricsById[record.Name] : 0;
var lastmoduser = record.LastModifiedBy;
if(lastmoduser){
console.log(lastmoduser['Name']);
}
var page = { Id: record.Id,
Name : record.Name,
CreatedDate : record.CreatedDate,
Views : parseInt(ct),
LastModifiedDate : record.LastModifiedDate,
LastModifiedBy : lastmoduser ? lastmoduser['Name'] : '',
LastModifiedById : lastmoduser ? lastmoduser['Id'] : ''
};
config.pages.push(page);
}
renderPages();
var formData = document.querySelector('div[id="formData"]');
formData.setAttribute('style','');
}
function renderPages(){
var output='';
var sorted = config.pages.sort(compareValues(config.sortKey,config.sortOrder));
for(var prop in sorted){
var page = sorted[prop];
output+=`<tr>
<th scope="row" data-label="${prop}"><div class="slds-truncate" title="${page.Name}"><a href="/${page.Id}">${page.Name}</a></div></th>
<td class="${page.Views == 0 ? 'slds-text-color_error' : ''}"><div class="slds-truncate" title="${page.Views}">${page.Views}</div></td>
<td><div class="slds-truncate" title="${convertDate(page.CreatedDate)}">${convertDate(page.CreatedDate)}</div></td>
<td><div class="slds-truncate" title="${convertDate(page.LastModifiedDate)}">${convertDate(page.LastModifiedDate)}</div></td>
<td><div class="slds-truncate" title="${page.LastModifiedBy}"><a href="/${page.LastModifiedById}">${page.LastModifiedBy}</a></div></td>
</tr>`;
//console.log(JSON.stringify(page, null, 4));
}
document.getElementById('output').innerHTML=output;
}
function convertDate(inputFormat) {
function pad(s) { return (s < 10) ? '0' + s : s; }
var d = new Date(inputFormat);
return [ pad(d.getMonth()+1),pad(d.getDate()), d.getFullYear()].join('/');
}
// function for dynamic sorting
function compareValues(key, order) {
order = order != undefined ? order : 'asc';
return function(a, b) {
if(!a.hasOwnProperty(key) || !b.hasOwnProperty(key)) {
// property doesn't exist on either object
return 0;
}
const varA = (typeof a[key] === 'string') ?
a[key].toUpperCase() : a[key];
const varB = (typeof b[key] === 'string') ?
b[key].toUpperCase() : b[key];
var comparison = 0;
if (varA > varB) {
comparison = 1;
} else if (varA < varB) {
comparison = -1;
}
return (
(order == 'desc') ? (comparison * -1) : comparison
);
};
}
document.addEventListener('DOMContentLoaded',function() {
var sel = document.querySelector('select[id="filterSince"]');
sel.onchange=changeEventHandler;
sel.value = config.since;
getMetrics();
},false);
function changeEventHandler(event) {
// You can use “this” to refer to the selected element.
var val = event.target.value;
console.log(val);
config.since = val;
getMetrics();
}
function resetSortUI(){
var selector ='.' + sortClass + ', .' + sortedDirClass();
var list = document.querySelectorAll(selector);
for (var item of list) {
item.classList.remove(sortClass,sortedDirClass());
}
}
function sortBy(elem, key, order){
resetSortUI();
if(config.sortKey === key){
config.sortOrder = config.sortOrder === 'asc' ? 'desc' : 'asc';
}else{
config.sortKey = key;
config.sortOrder = order !== undefined ? order : 'desc';
}
console.log(elem.parentNode);
elem.parentNode.classList.add(sortClass,sortedDirClass());
renderPages();
}
</script>
<div class="metricsBody slds-scope">
<apex:sectionHeader title="VisualForce Page Metrics"
description="This page displays your organization's VisualForce page usage, by views."
help="https://developer.salesforce.com/docs/atlas.en-us.pages.meta/pages/pages_tools_metrics.htm"/>
<div id="formData" style="display:none;">
<div class="slds-grid">
<div class="slds-col">
<div data-reactroot="" class="slds-form slds-form_stacked slds-m-bottom_medium">
<div data-reactroot="" class="slds-form-element">
<label class="slds-form-element__label" for="filterSince">Metrics Since: </label>
<div class="slds-form-element__control">
<div class="slds-select_container slds-size_small">
<select class="slds-select" id="filterSince">
<option value="YESTERDAY">Yesterday</option>
<option value="LAST_WEEK">Last Week</option>
<option value="LAST_MONTH">Last Month</option>
<option value="LAST_YEAR">Last Year</option>
<option value="">All Time</option>
</select>
</div>
</div>
</div>
</div>
</div>
</div>
<table id="dataTable" data-reactroot="" class="slds-table slds-table_bordered slds-table_resizable-cols slds-table_fixed-layout" role="grid">
<thead>
<tr class="slds-text-title_caps slds-line-height_reset">
<th class="slds-is-sortable slds-text-title_caps" scope="col" id="filter_Name">
<a href="javascript:void(0);" onclick="sortBy(this,'Name')" class="slds-th__action slds-text-link_reset" tabindex="0">
<span class="slds-assistive-text">Sort </span>
<span class="slds-truncate" title="Name">Name</span>
<div class="slds-icon_container">
<svg class="slds-icon slds-icon_x-small slds-icon-text-default slds-is-sortable__icon" aria-hidden="true">
<use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="{!URLFOR($Asset.SLDS,'assets/icons/utility-sprite/svg/symbols.svg#arrowdown')}"></use>
</svg>
</div>
<span class="slds-assistive-text" aria-live="assertive" aria-atomic="true"></span>
</a>
</th>
<th class="slds-is-sortable slds-text-title_caps slds-is-sorted slds-is-sorted_desc" scope="col" id="filter_Views">
<a href="javascript:void(0);" onclick="sortBy(this,'Views')" class="slds-th__action slds-text-link_reset" tabindex="0">
<span class="slds-assistive-text">Sort </span>
<span class="slds-truncate" title="Views">Views</span>
<div class="slds-icon_container">
<svg class="slds-icon slds-icon_x-small slds-icon-text-default slds-is-sortable__icon" aria-hidden="true">
<use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="{!URLFOR($Asset.SLDS,'assets/icons/utility-sprite/svg/symbols.svg#arrowdown')}"></use>
</svg>
</div>
<span class="slds-assistive-text" aria-live="assertive" aria-atomic="true"></span>
</a>
</th>
<th class="slds-is-sortable slds-text-title_caps" scope="col" id="filter_CreatedDate">
<a href="javascript:void(0);" onclick="sortBy(this,'CreatedDate');" class="slds-th__action slds-text-link_reset" tabindex="0">
<span class="slds-assistive-text">Sort </span>
<span class="slds-truncate" title="Created Date">Created Date</span>
<div class="slds-icon_container">
<svg class="slds-icon slds-icon_x-small slds-icon-text-default slds-is-sortable__icon" aria-hidden="true">
<use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="{!URLFOR($Asset.SLDS,'assets/icons/utility-sprite/svg/symbols.svg#arrowdown')}"></use>
</svg>
</div>
<span class="slds-assistive-text" aria-live="assertive" aria-atomic="true"></span>
</a>
</th>
<th class="slds-is-sortable slds-text-title_caps" scope="col" id="filter_LastModifiedDate">
<a href="javascript:void(0);" onclick="sortBy(this, 'LastModifiedDate');" class="slds-th__action slds-text-link_reset" tabindex="0">
<span class="slds-assistive-text">Sort </span>
<span class="slds-truncate" title="Created Date">Last Modified Date</span>
<div class="slds-icon_container">
<svg class="slds-icon slds-icon_x-small slds-icon-text-default slds-is-sortable__icon" aria-hidden="true">
<use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="{!URLFOR($Asset.SLDS,'assets/icons/utility-sprite/svg/symbols.svg#arrowdown')}"></use>
</svg>
</div>
<span class="slds-assistive-text" aria-live="assertive" aria-atomic="true"></span>
</a>
</th>
<th class="slds-is-sortable slds-text-title_caps" scope="col" id="filter_LastModifiedBy">
<a href="javascript:void(0);" onclick="sortBy(this, 'LastModifiedBy');" class="slds-th__action slds-text-link_reset" tabindex="0">
<span class="slds-assistive-text">Sort </span>
<span class="slds-truncate" title="Created Date">Last Modified By</span>
<div class="slds-icon_container">
<svg class="slds-icon slds-icon_x-small slds-icon-text-default slds-is-sortable__icon" aria-hidden="true">
<use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="{!URLFOR($Asset.SLDS,'assets/icons/utility-sprite/svg/symbols.svg#arrowdown')}"></use>
</svg>
</div>
<span class="slds-assistive-text" aria-live="assertive" aria-atomic="true"></span>
</a>
</th>
</tr>
</thead>
<tbody id="output">
</tbody>
</table>
</div>
</div>
<apex:outputPanel rendered="{!$User.UIThemeDisplayed == 'Theme4d' || $User.UIThemeDisplayed == 'Theme4u' }" >
<style id="{!$User.UIThemeDisplayed}">
.metricsBody {
padding: 1em 2em;
}
body .bDescription, body .bPageTitle{
margin-bottom:1em;
}
body .bPageTitle .pageType{
font-size: 2rem;
}
</style>
</apex:outputPanel>
</apex:page>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment