This opportunity analysis report is an attempt to visualize a summary of the state of an opportunity, showing where in the process an opportunity is instead of showing just the sales stage, and displaying KPI’s using color instead of just a series of numbers.

Disclaimer: This is not a finished report and should not be considered as such.  This is just a proof of concept to show what the reporting engine of CRM On Demand is capable of.

HTML5 Canvas and Javascript are not a required skill for normal CRM On Demand report generation at all!  But using these techniques enable a wide range of unusual data visualizations.

Here is all you need to make this opportunity analysis report in CRM On Demand.  But before you try this out, you might want to learn more about how narrative views actually work by checking out this video recording

Result Example

oppty analysisConcepts

  • Showing where the opportunity is in the sales process
  • Showing a KPI value not just with a calculated value, but by adding a color that compares the value to a certain expectation

Criteria Fields

From the ‘Reporting’ subject areas, I used: ‘Opportunities’

Field Name Calculated Field Formula
Opportunity Name Opportunity.Name
Sales Stage Opportunity.”Sales Stage”
Probability Opportunity.”Probability %”
Days till close date
Expected Revenue  Yes CAST(“Opportunity Metrics”.”Expected Revenue” / 1000 AS CHAR)

Criteria Filters

  • A filter to only evaluate opportunity of the same opportunity type.  Mixing opportunity types will lead to having sales stages of different opportunity types mixed up into a flow that is not representable, unless that would be built in further into the narrative report.
  • A filter to only show the opportunity matching 1 specific opportunity ID or name.

Data Formatting

Format the date till the table view looks something like the example below.

oppty analysis tableHide the table once the narrative view is ready.

Narrative Warning

As this report relies on the use of multiple views, as many as you need, especially for the tiles, you need to make sure that the first few lines in the prefix contain a unique identifier for each of them:

<canvas id="tile1" width="800" height="50"></canvas>     
<script>       
var canvas = document.getElementById('tile1');
 ...
<canvas id="tile2" width="800" height="50"></canvas>     
<script>       
var canvas = document.getElementById('tile2');
 ...
<canvas id="tile3" width="800" height="50"></canvas>     
<script>       
var canvas = document.getElementById('tile3');

Narrative View Definition 1: Process Flow

Prefix

    <canvas id="myCanvas" width="800" height="50"></canvas>
    <script>
      var canvas = document.getElementById('myCanvas');
      var context = canvas.getContext('2d');

      var flow = [];
      flow[0] = 'Qualified Lead';
      flow[1] = 'Building Vision';
      flow[2] = 'Short List';
      flow[3] = 'Selected';
      flow[4] = 'Negotiation';
      flow[5] = 'Closed/Lost';
      flow[6] = 'Closed/Won';

      var params = [];
      params['canvasWidth'] = canvas.width;
      params['canvasHeight'] = canvas.height;
      params['stageWidth'] = Math.round(canvas.width / flow.length);

      function drawStage(i, salesStage, flowStage) {
         x = i * params['stageWidth'];
         y1 = i;
         y3 = canvas.height;
         y2 = y1 + Math.round((y3 - y1) / 2);
         w = params['stageWidth'];
         s = 12;

         context.beginPath();
         context.moveTo(x, y1);
         context.lineTo(x + w - s, y1);
         context.lineTo(x + w, y2);
         context.lineTo(x + w - s, y3);
         context.lineTo(x, y3);
         context.lineTo(x + s, y2);
         if (salesStage == flowStage) {
            context.fillStyle = 'red';
         } else {
            context.fillStyle = 'blue';
         }
         context.fill();

         context.font = '10pt Arial';
         context.fillStyle = 'white';
         context.textAlign = 'center';
         context.textBaseline = 'middle';
         context.fillText(flowStage, x + Math.round(w / 2), y2);
      }

      function drawFlow(salesStage) {
         for (i = 0; i < flow.length; i++) { 
           drawStage(i, salesStage, flow[i]);
         }
      }

Narrative

drawFlow('@2');

Postfix

</script>

Rows to Display: empty

Narrative View Definition 2, 3, 4: KPI Tile

Prefix

    <canvas id="myTile1" width="150" height="150"></canvas>
    <script>
      var canvas = document.getElementById('myTile1');
      var context = canvas.getContext('2d');

      var params = [];
      params['canvasWidth'] = canvas.width;
      params['canvasHeight'] = canvas.height;

      function drawText(text, order, size) {
         x = Math.round(canvas.width / 2);
         y = Math.round(params['canvasHeight'] / 3) * order;

         context.font = size + 'pt Arial';
         context.fillStyle = 'white';
         context.textAlign = 'center';
         context.textBaseline = 'middle';
         context.fillText(text, x, y);
      }

      function drawTile(label, value) {
         x = 0;
         y = 0;
         w = canvas.width;
         h = canvas.height;

         context.beginPath();
         context.rect(x, y, w, h);
         context.fillStyle = 'green';
         context.fill();

         context.beginPath();
         context.rect(x + 5, y + 5, w - 10, h - 10);
         context.lineWidth = 2;
         context.strokeStyle = 'white';
         context.stroke();

         drawText(label, 1, 10);
         drawText(value, 2, 30);
      }

Narrative

drawTile('Probability', '@3'+'%');

Postfix

</script>

Rows to Display: empty

Recommended Posts

Leave A Comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.