Plot your Salesforce Leads on a map

Plot your Salesforce Leads on a map

With my first Salesforce blog post I thought I’d dive right in to a write-up and example of a feature in particular. As of the Spring ‘16 release of Salesforce, standard address fields have had automatic geocoding applied to them. In this blog post, I’ll show how to quickly and easily create a Lightning component (based heavily on: Creating a Lightning Map Component) that plots leads on a map, calculating the distance to them when an individual lead is inspected. I’ve done all of this work in a Developer Edition environment, so I can vouch that it works! This blog post assumes familiarity with the lightning interface and the developer console.

 

Re-visited: Creating a Lightning Map Component

Salesforce Developer Relations very helpfully wrote the above blog post to illustrate just how simple and easy it is to create Lightning components, and in particular being able to create a map that plots a single marker showing where Dreamforce is hosted. I’ve used that example as the basis from which we can then use automatic geocoded data to plot leads. If you aren’t familiar with it, I strongly advise you give it a read.

 

Create custom fields on the user object

The first thing we’ll need to do is create a custom field on the User object to state our base location (imagine we’re the salesperson - we’re setting the lat/long of our office or wherever we’re based). Create the following field:

  • Type: Geolocation
  • Name: Base location

Add to the page layout in the standard manner. When done, populate a latitude and longitude in your new custom field for your user record.

 

Create the Server-side controller class to retrieve current user and lead information

Next, open the developer console and create a new Apex Class. Call it “LeadVisualiserSSController”. Change the class definition to this:

public with sharing class LeadVisualiserSSController {
    @AuraEnabled
    public static List<Lead> getLeads() {
        return [
            SELECT Id, Name, Latitude, Longitude
            FROM Lead
            WHERE OwnerId = :UserInfo.getUserId() AND Latitude != NULL AND Longitude != NULL
        ];
    }

    @AuraEnabled
    public static User getUserInfo() {
        return [
            SELECT Id, Name, Base_Location__Latitude__s, Base_Location__Longitude__s
            FROM User
            WHERE Id = :UserInfo.getUserId()
        ];
    }
}

Creating the Lead Visualiser component

Create a Lightning component called “Lead Visualiser” from the developer console.

Next, we’ll add the code for the component markup, controller, helper and styling.

 

Add the Leaflet mapping library

Follow the step entitled “Import Leaflet as a Static Resource” from Creating a Lightning Map Component to import the Leaflet library.

 

Component

The following code will define the component markup. This does a number of things:

  • Specifies the server-side controller
  • Creates an array to store lead information
  • Creates a User object definition
  • Instantiates the Leaflet map library
  • Creates a division to hold the map itself

 

<aura:component implements="force:appHostable" controller="LeadVisualiserSSController">

    <aura:attribute name="leads" type="Lead[]" />
    <aura:attribute name="userInfo" type="User" />

    <ltng:require styles="/resource/leaflet/leaflet.css" />
    <ltng:require scripts="/resource/leaflet/leaflet.js" afterScriptsLoaded="{!c.mapLoaded}" />

    <div class="map" id="map"></div>
</aura:component>

Controller

Things now start to get interesting. We need to instantiate our map, get user data, get leads data, plot the leads on the map as markers, but not before we’ve calculated the distance from the base lat/long on our user record so we can display that info when a marker is clicked. Phew!

({
    mapLoaded: function(component, event, helper) {
      // Get a handle on our server-side controller methods
      var leadsAction = component.get("c.getLeads");
      var userAction = component.get("c.getUserInfo");

      // Instantiate the user and leads objects - these are populated later
      var userInfo = {};
      var leads = {};

      // Set initial map parameters
      var map = window.L.map("map", {zoomControl: true});

      // Instantiate the map
      window.L.tileLayer("https://server.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer/tile/{z}/{y}/{x}",
      {
         attribution: "Tiles © Esri"
      }).addTo(map);

      // Set the default view of the map based on the users location
      map.locate({setView: true, maxZoom: 16});

      // Set the leads callback functionality
      leadsAction.setCallback(
         this,
         function(response) {
            var state = response.getState();

            // Haversine Distance is explained in the Helper
            var haversineDistance;

            if (component.isValid() && state === "SUCCESS") {
               // Put the user information into the leads variable
               leads = response.getReturnValue();
               component.set("v.leads", leads);

               // Get all Leads and plot as Markers
               for (var i = 0; i < leads.length; i++) {
                  if (leads[i].Latitude !== null && leads[i].Longitude !== null) {
                     // Calculate the Haversine Distance. Again, Haversine Distance is explained in the Helper
                     haversineDistance = helper.calculateHaversineDistance(leads[i].Latitude, leads[i].Longitude, userInfo.Base_Location__Latitude__s, userInfo.Base_Location__Longitude__s);
                     // Draw the markers on the map, with the Lead Name and calculated Distance
                     L.marker([leads[i].Latitude, leads[i].Longitude]).addTo(map)
.bindPopup(leads[i].Name + "<br />Distance from your base location: " + haversineDistance + " miles");
               }
            }
         }
      }
   );

   // Set the user information callback functionality
   userAction.setCallback(
      this,
      function(response) {
         var state = response.getState();

         if (component.isValid() && state === "SUCCESS") {
            // Put the user information into the userInfo variable
            userInfo = response.getReturnValue();
            component.set("v.userInfo", userInfo);
         }
      }
   );

   // Lastly, queue up the server-side calls
   $A.enqueueAction(userAction);
   $A.enqueueAction(leadsAction);
   }
})

 

Helper

Use the following code for the Helper: 

({
    // Calculate the Haversine Distance between a pair of lat/long co-ordinates.
   // See "What formulae does the Geolocation Distance" at http://salesforce.stackexchange.com/questions/32585/what-formulae-does-the-geolocation-distance-use for more information
   calculateHaversineDistance: function(lat1, lon1, lat2, lon2) {
      // Earth's radius varies from 6356.752 km at the poles to 6378.137 km at the equator
      var radius = 6371.00;
      var dLat = this.toRadians(lat2 - lat1);
      var dLon = this.toRadians(lon2 - lon1);
      var a = Math.sin(dLat/2) * Math.sin(dLat/2) +
         Math.cos(this.toRadians(lat1)) * Math.cos(this.toRadians(lat2)) *
         Math.sin(dLon/2) * Math.sin(dLon/2);
      var c = 2 * Math.asin(Math.sqrt(a));
      var kmToMiles = 0.621371;

      return (radius * c * kmToMiles).toFixed(2);
   },

   // Given a degree, calculate the value in radians
   toRadians: function(degree) {
      return ((degree * 3.1415926) / 180);
   }
})

 

Styling

This one is simple, thankfully!

.THIS.map {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
}

You’re done creating the Lightning component! Save everything! Next, we’ll create the tab definition.

 

Make Lead Visualiser visible to use

In Setup, click Create > Tabs. Click New in the Lightning Component Tabs section.

Select “c:Lead Visualiser” as the Lightning Component. Specify “Lead Visualiser” as the Tab Label and “Lead_Visualiser” as the Tab Name.

Click the magnifier icon and select a tab icon of your choice. Click Next and Save.

 

Try it!

Finally, load the component in Salesforce Lightning. From the App Launcher, select “Other Items” and select “Lead Visualiser”. Here’s the finished result.

Of course, having the user location automatically update based on location would be awesome to facilitate automatic distance calculations. This could be done by creating an Apex web service and having the Leaflet map automatically update the user location at given intervals.

Enjoy exploring the power of geocoding and location-based services in Salesforce! I’d love to hear thoughts and ideas. I’m at http://twitter.com/aaronallport

Hi Aaron ! Thank you so much for your blog post. I wonder if you can help me with the last step (Making Lead visible)  ? I went to Tabs but I can not find any Lightning Components Tab section. I just saw Lightning Page section. I looked for answers on google but I could not find one. Thank you 

Like
Reply

Ceasar Sabarre you might like this one.

Like
Reply

To view or add a comment, sign in

More articles by Aaron Allport

  • Disconnecting from work, and being given the space to do so

    In June I was searching the internet for family holiday package deals for August of this year. August seemed to come…

    2 Comments
  • Why I'm (still) at Slalom after 4 years

    In January 2015 I took an offer of a job for a new-to-the-market Business and Technology consultancy called Slalom. I…

  • Salesforce Certified Data Architecture & Management Designer Exam Tips

    Last week saw the revision pay off as I passed my first Salesforce Architect Designer exam. I’ll share some tips that I…

    6 Comments
  • Dreamforce 2017

    Familiar territory The 4th of November 2017 marked the day I boarded a plane and flew to San Francisco (Virgin…

    2 Comments
  • Salesforce World Tour London 2017

    The 18th of May 2017 saw the Salesforce World Tour come to the ExCeL in London. The largest Salesforce event outside of…

    1 Comment
  • London's Calling 2017

    On the 10th of February 2017, I attended London’s Calling ‘17 after winning a free ticket in a retweet competition…

    1 Comment
  • 5 JavaScript tips for Visualforce Pros

    JavaScript is the double-edged sword of browser magic and copious head-scratching trying to get your code working. As…

  • 5 TIPS TO GO FROM VISUALFORCE TO #LIGHTNING

    Tip 1: Client-side FTW! One of the major changes introduced with the Salesforce Lightning framework is that it…

  • Dreamforce 2016. First time attending, first time speaking

    Back in August, I wrote a blog post to highlight the automatic geocoding feature new to the Summer ‘16 release of…

    4 Comments
  • New and improved Salesforce Leads on a map

    Hot on the heels of Plot your Salesforce leads on a map, I’ve made some updates to the code to improve the experience…

Others also viewed

Explore content categories