Subscribe

Appirio RSS 

Feed
Subscribe with Bloglines

Add to Google
Subscribe in 

NewsGator Online

Community

Appirio Technology Blog

Thursday, October 2, 2008

Google Earth Integration via Visualforce

 

The VisualForce "contentType" page attribute makes it easy to push data from Salesforce directly to other apps. Here, we'll review an example using Google Earth. We use KML to view Salesforce Opportunities on a 3D map. Let's start with the page itself:

    <apex:page controller="KMLController" cache="true" showHeader="false" contentType="application/vnd.google-earth.kml+xml">
    <kml xmlns="http://earth.google.com/kml/2.0">
    <Document>
    <name>Salesforce Opportunities</name>
    <apex:repeat value="{!oppList}" var="o">
    <Placemark>
    <name>{!o.Name}</name>
    <address>{!o.Account.BillingStreet} {!o.Account.BillingCity}, {!o.Account.BillingState} {!o.Account.BillingPostalCode}</address>
    <description>
    <![CDATA[
    <p><b>Account: </b>{!o.Account.Name}
    <p><b>Amount: </b>${!o.Amount}
    <p><b>Close Date: </b>{!MONTH(o.CloseDate)}/{!DAY(o.CloseDate)}/{!YEAR(o.CloseDate)}
    ]]>
    </description>
    </Placemark>
    </apex:repeat>
    </Document>
    </kml>
    </apex:page>
    Note the following:
      • The contentType="application/vnd.google-earth.kml+xml" attribute notifies the browser that the page content should be passed to Google Earth.

      • The cache="true" attribute addresses this IE security issue.

      • The meat of the page is in an <apex:repeat> block that iterates over a list of Opportunities. In this example, we're mapping the opportunity address, but you could use the Geocoding API to specify a Point with specific longitude and latitude coordinates

        The page controller retrieves a List of Opportunity objects based on a comma-delimited URL parameter:

        public class KMLController {

        public Opportunity[] oppList {get; set;}

        public KMLController() {

        String sel = '';

        if (null != ApexPages.currentPage().getParameters().get('sel')) {

        sel = ApexPages.currentPage().getParameters().get('sel');

        }

        String[] idList = sel.split(',', 0);

        oppList = [SELECT Id, Name, Amount, CloseDate,

        Account.Name, Account.BillingStreet, Account.BillingCity,

        Account.BillingState, Account.BillingPostalCode

        FROM Opportunity

        WHERE id IN :idList];

        }

        }

        Finally, an Opportunity custom button is used to invoke the VisualForce page, passing a list of selected Opportunity Id's from a List View or Related List:

        var sel = {!GETRECORDIDS( $ObjectType.Opportunity)};

        if (!sel.length) {

        alert("Please select at least one opportunity for mapping.");

        } else {

        var d = new Date(); // Append milliseconds to URL to avoid browser caching

        url= "/apex/KMLPush?ms=" + d.getTime() + "&sel=" + {!GETRECORDIDS( $ObjectType.Opportunity)};

        window.location.href=url;

        }

        When the button is clicked, the selected Opportunities will be displayed (via KML) in Google Earth.

        10-2-2008 8-50-13 PM

        If the KML file doesn't open properly, you might need to manually add the following Windows registry entries:

        [HKEY_LOCAL_MACHINE\SOFTWARE\Classes\MIME\Database\Content Type]

        [HKEY_LOCAL_MACHINE\SOFTWARE\Classes\MIME\Database\Content Type\application/vnd.google-earth.kml+xml]

        "Extension"=".kml"

        [HKEY_LOCAL_MACHINE\SOFTWARE\Classes\MIME\Database\Content Type\application/vnd.google-earth.kmz]

        "Extension"=".kmz"

        Labels:

        Spread the word:  del.icio.us Bookmark it!    submit Google Earth Integration via Visualforce to digg.com Digg it!    Technorati Related

        posted by Appirio at 7:53 PM   Permalink »

        Tags: ,, , ,

        4 Comments:

        At October 6, 2008 6:21 PM, Blogger brian said...

        Dan,
        This is great and I got it working on my system. What changes would be needed to adapt it for Google Maps?

        Would contentType="application/x-www-form-urlencoded" and kml xmlns="http://maps.google.com/maps/geo". Also would I need to include the SF server key?
        Thanks.

         
        At October 7, 2008 12:41 PM, Blogger Dan Guggenheim said...

        Brian -

        There are a quite a few examples that show how one can mashup Salesforce and Google Maps. However, most of them use the Maps API instead of KML. (And, yes, this requires a key tied to the domain of your salesforce.com server.)

        The mechanism for passing a KML file to Google Maps is to put the KML/KMZ file on a public website and then pass the URL to Google Maps, like this.

        Since Apex typically runs under an authenticated session, there's no way for Google to "call back" to Apex and/or VisualForce to retrieve the KML "page" in our example. You'd need a publicly accessible, external process to retrieve the locations from SFDC and pass them back to Google in KML format.

        The Salesforce "Public Sites" functionality that's coming might provide a cleaner solution in the future.

         
        At December 2, 2008 1:10 PM, Blogger neutronron said...

        Dan,

        Is the cache="true" fix for the IE7 problem still working for you?

         
        At December 3, 2008 6:08 PM, Blogger Dan Guggenheim said...

        Yes it still seems to work, though IE sometimes wants to prompt before downloading the file.

        At one point, I had to add some registry entries to associate .kml files with the Google Earth app. Those entries can be found at the end of the original post.

         

        Post a Comment

        << Home