This boardgame like any type of gamification visualization tries to create some competition between participants.
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 boardgame 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
Concepts
- The base report is one where activities per salesrep are counted, but anything could be counted
- The activity count is capped at 20
- The incentives can be entered in the narrative view prefix definition. The colors and center image can be changed there too
Criteria Fields
From the ‘Reporting’ subject areas, I used: ‘Activities’
Field Name | Calculated Field | Formula |
---|---|---|
Salesrep | Account.Owner | |
# Activities | Yes | CASE WHEN “Activity Metrics”.”# of Activities” > 20 THEN 20 ELSE “Activity Metrics”.”# of Activities” END |
Rep # | Yes | RSUM(COUNT(DISTINCT 1)) |
# Reps | Yes | SUM(COUNT(DISTINCT 1)) |
Criteria Filters
- Any filter to count activities in a certain timeframe
- Any filter that limits the count of activities to only a specific type of activities
Data Formatting
Format the date till the table view looks something like the example below.
Hide the table once the narrative view is ready.
Narrative View Definition
Prefix
<canvas id="myCanvas" width="800" height="800"></canvas> <script> var canvas = document.getElementById('myCanvas'); var context = canvas.getContext('2d'); var params = []; params['tilesPerXSide'] = 6; params['tilesPerYSide'] = 6; params['boardBorder'] = 5; params['tileBorder'] = 3; params['maxWidth'] = canvas.width; params['maxHeight'] = canvas.height; params['countTiles'] = 2 * params['tilesPerXSide'] + 2 * params['tilesPerYSide'] - 4; var board = []; for (var i = 1; i <= params['countTiles'] ; i++) { board[i] = []; board[i]['reward'] = ''; board[i]['players'] = []; board[i]['tileColor'] = 'white'; board[i]['tileEdgeColor'] = 'red'; board[i]['tileNumberColor'] = '#F0F0F0'; board[i]['tileRewardColor'] = 'white'; board[i]['tilePlayerColor'] = 'blue'; } setReward(5, '1 x Champagne'); setReward(10, '6 x Champagne'); setReward(15, '12 x Champagne'); setReward(20, 'City trip for 2'); context.beginPath(); context.rect(0, 0, canvas.width, canvas.height); context.lineWidth = 1; context.fillStyle = 'white'; context.fill(); context.strokeStyle = 'black'; context.stroke(); var image = new Image(); image.onload = function() { context.drawImage(image, canvas.width / 2 - 128, canvas.height / 2 - 128 - 50); }; image.src = 'http://www.technogist.com/wp-content/uploads/2014/05/Oracle-logo.png'; context.font = '20pt Calibri'; context.textAlign = 'center'; context.textBaseline = 'middle'; context.fillStyle = 'red'; context.fillText('Score small deals in FY15 (less than $100k)', canvas.width / 2, canvas.height / 2 + 100); function setReward(tileID, reward) { board[tileID]['reward'] = reward; board[tileID]['tileColor'] = 'red'; board[tileID]['tileEdgeColor'] = 'red'; board[tileID]['tileNumberColor'] = '#FF8181'; board[tileID]['tileRewardColor'] = 'white'; board[tileID]['tilePlayerColor'] = 'blue'; } function drawTiles(params, tileID, board) { var tileWidth = Math.round((params['maxWidth'] - (2 * params['boardBorder']) - (2 * params['tileBorder'])) / params['tilesPerXSide']); var tileHeight = Math.round((params['maxHeight'] - (2 * params['boardBorder']) - (2 * params['tileBorder'])) / params['tilesPerYSide']); if (tileID <= params['tilesPerXSide']) { x = params['tileBorder'] + params['boardBorder'] + ((tileID - 1) * tileWidth); y = params['tileBorder'] + params['boardBorder']; } else if (tileID <= params['tilesPerXSide'] + params['tilesPerYSide'] -1) { x = params['tileBorder'] + params['boardBorder'] + ((params['tilesPerXSide'] - 1) * tileWidth); y = params['tileBorder'] + params['boardBorder'] + ((tileID - params['tilesPerXSide']) * tileHeight); } else if (tileID <= 2*params['tilesPerXSide'] + params['tilesPerYSide'] -2) { var offsetX = tileID - params['tilesPerXSide'] - params['tilesPerXSide'] + 1; x = params['tileBorder'] + params['boardBorder'] + ((params['tilesPerYSide'] - offsetX - 1) * tileWidth); y = params['tileBorder'] + params['boardBorder'] + ((params['tilesPerYSide'] - 1) * tileHeight); } else if (tileID <= 2*params['tilesPerXSide'] + 2*params['tilesPerYSide'] -4) { var offsetY = tileID - 2*params['tilesPerXSide'] - params['tilesPerYSide'] +2; x = params['tileBorder'] + params['boardBorder']; y = params['tileBorder'] + params['boardBorder'] + ((params['tilesPerYSide'] - offsetY - 1) * tileHeight); } // draw Tile context.beginPath(); context.rect(x, y, tileWidth, tileHeight); context.fillStyle = board[tileID]['tileColor']; context.fill(); context.lineWidth = params['tileBorder']; context.strokeStyle = board[tileID]['tileEdgeColor']; context.stroke(); // write tile number context.font = '60pt Calibri'; context.textAlign = 'center'; context.textBaseline = 'middle'; context.fillStyle = board[tileID]['tileNumberColor']; context.fillText(tileID, x + tileWidth/2, y + tileHeight/2); // write reward context.font = '12pt Calibri'; context.textAlign = 'center'; context.fillStyle = board[tileID]['tileRewardColor']; context.fillText(board[tileID]['reward'], x + tileWidth/2, y + 10); var k = board[tileID]['players'].length; if (k > 0) { for (var i = 0; i < k; i++) { context.font = '12pt Calibri'; context.textAlign = 'center'; context.fillStyle = board[tileID]['tilePlayerColor']; context.fillText(board[tileID]['players'][i], x + tileWidth/2, y + 10 + 14 * (i+2)); } } }
Narrative
var j = board[@2]['players'].length; board[@2]['players'][j] = '@1';
Row separator: empty
Postfix
for (var i = 1; i <= params['countTiles'] ; i++) { drawTiles(params, i, board); } </script>
Rows to Display: empty