Sep 22, 2014

Lab Coat Lesson: Using Bootstrap in Visualforce


During the Summer of Hacks last July, I worked with a pair of coders with no prior Salesforce experience. While I worked on the Apex code, I had them work on the front end because Visualforce could just be straight up HTML if you wanted it to be. So the devs - both of whom had far more experience in modern front-end tools and libraries than I did - decided to use Bootstrap for the front end. But this decision came with a stipulation:

"We had to disable the header and standard style sheets for it to work."

This was okay to me for the time because we were building a Salesforce1 app and the mobile container did not require any headers. But now I want the page to function normally in desktop Salesforce just as well as the mobile version, I put the header and standard stylesheet back on.



Yuck! That's no good! Look at what happened to the Salesforce header and tabs. There is obviously some kind of CSS being overridden from the third-party library to Salesforce. Time to figure out how to use Bootstrap and Salesforce together.


Sep 15, 2014

Lab Coat Lesson: Building better Analytic Snapshots



Analytic snapshots should be in every admins toolbox. The ability to report on historical data and track trends over time is beneficial to nearly all organizations. Salesforce Help & Training documentation is a good place to start for beginners learning to setup and configure analytic snapshots for their organization.

Here are some useful tips, best practices, and workarounds for the admin looking to make analytic snapshots more efficient:
  • Find out how Schema Builder can save you clicks and time 
  • Map a lookup field 
  • Use record types in analytic snapshots 
  • Save and protect your working in a secure report folder 

Use the Schema Builder to create your target object and fields!

Create your target object using the Schema Builder. You most likely will not be creating a tab for this object and will not need to use the Wizard for this object. This is the most efficient method for creating or target object to house the fields and data of the source report. You will save many clicks using the schema builder instead of adding fields to an object from the setup menu.

Click Setup > Schema Builder. This is a drap-and-drop environment you can use to create your new target object and all the necessary fields to map from the source report.

First, click on the Elements tab and drag Object into the work pane.

NOTE: Make sure you select Allow Reports or you will have trouble later!



It is recommended that you create your source report first. This way, you will know which fields you want to archive. You can quickly create the fields in the target object based on the fields in the source report.

Using the Schema Builder, drag a field type from the side panel and drop it in your new target object. The field types must be compatible. Most are pretty straightforward, you will usually use the same data type from the source field for your target field (for example, the Amount field maps to a currency field). Make sure you pay attention to field length and decimal places for currency, number, and percent fields. Make sure text fields have at least the same character length. There are some trickier scenarios which will we cover now…

Mapping a Lookup Field:

Following our example of creating an opportunity analytic snapshot, how would we archive the Account Name of the opportunity? This is a lookup field, so create a lookup field related to the Accounts in the target object.

To map a value to this lookup field, you must map the Account ID. Make sure Account ID is included in your source report.


Mapping Record Types

Unfortunately, and despite grumblings from the Salesforce community, you cannot map record types in an analytic snapshot. There is however, an easy workarounds using formula fields. We will store the record type name in a custom field, include this field in the source report, and map it to a text field on the target object.

Formula Field for Record Types

Here at CRM Science, we found an even easier way to map record types to analytic snapshots than this Salesforce knowledge article suggests: Can I map the record type in an Analytic Snapshot?

It recommends creating a text formula field and entering the following formula:



You see, following this articles advice, you would have to actively manage your formula. What if you created new record types? Or changed the name of an existing record type? You would have to update the formula.

Follow this simple advice to create the formula and forget it! It will manage itself.

  1. Create a Text Formula Field on the object 
  2. Name it “Record Type” or something similar. I do not use “Opportunity Record Type” in order to distinguish it from the standard's field name. 
  3. Enter the following into the formula:  “RecordType.Name”
  4. Save and forget it! 
This formula will simply copy the record type name into the field. No need for all that extra code that you will have to remember to update later when record types change.

Create an “Analytic Snapshot” folder to protect all your hard work

The last thing you need is to setup, configure, and schedule the analytic snapshot only to have an end user make change to the source report and ruin everything!

I cannot stress this enough, save your source report to a folder that is Read Only, or grant only Viewer access if the new report sharing model is enabled, to all users except those trusted to make changes to analytic snapshots.

If non-admins have edit access to the source report, they can (and we all know, will) edit the report. This puts all the field mappings at risk of breaking and your analytic snapshot failing. So protect your hard work and create a Read Only report folder for your source report!

This advice should prove useful for seasoned analytic snapshot creators. If you are new to analytic snapshots, remember these tips! To get started, check out this page to learn how to setup and configure analytic snapshots: Report on Historical Data with Analytic Snapshots.

Sep 8, 2014

Lab Coat Lesson: The Google Maps API



This blog post will discuss the various Google Maps Web API’s and their features. We will show you a few ways to use them in your next Salesforce project and give you some sample code to get you started right away. You will be able to add maps to your record details, in pdf’s, custom visualforce pages and with a little thought anywhere else you so desire within your Salesforce instance. Your best help on this adventure will be from Google itself at http://developers.google.com/maps/.

We will be covering the following Google Maps API's :
Embed - allows you to iframe a map
Geocoding - get the coordinates for an address
Static Map - create an image of a map
JavaScript - fully customizable map 

Instant Gratification: Google Maps Embed API
Do you have a record with an address field on it and desire to show it’s location on a map? The Embed API will accomplish that for you with very little effort on your part. With a couple dozen lines of code you can create an inline visualforce page on an object of your choice (such as Account or Lead) that shows the record's location! Here’s the finished product:



Here is the visualforce code that produced this: 


All we are doing here is passing in the address fields as parameters into the iframe source.

**Don’t forget to add http://maps.googleapis.com to your Remote Site Settings! We keep it simple for now and assume that the record has values for the Street Address, City, State, Zip Code, and Country fields. The controller gathers these values for the page like so:



That’s all there is to it! This can be extended further by passing the “Mode” parameter, for example directions. You could even potentially show directions based on records of a related list by passing all of their addresses as parameters to the iframe src.

Latitude and Longitude? Google Maps Geocoding API
Geocoding standardizes your addresses with high accuracy, a very important need in businesses. Slight variations in addresses can lead to dramatically different interpretations as to their physical locations. Different parts of the world build their addresses in different ways. And do we really want to keep lugging around all those various fields each time we try to map? Using a latitude and a longitude sets the frame of reference to an exact point on the sphere that is our dear planet Earth. This also serves as an address validation tool — failure to return a latitude and longitude pair would imply that the location could not be found in the Google (in this case) database. 

We’ll add this code to the page controller we created earlier so we can perform a geocode through the page while viewing the record. Let’s see how it’s done:


We added a button and an output field to see what we’re doing from the inline visualforce page we built earlier:


The result is this :


We pressed the button, geocoded the address, printed the result on the page, and also updated the record’s address field with the coordinates. Geocoded!

Need an image? Google Maps Static API
Suppose you would like to include your new map in a pdf. Well, we can’t go about embedding something dynamic like an <iframe> in a pdf, but what we can do is get an image of the map and embed that instead. The image tag could be stored somewhere like a field on the record, perhaps built in the controller from address fields in the record. Here is the result:


Image__c here is a rich text field that simply contains an image tag with an src leading to the Static Maps API endpoint, passing in lat/lng coordinates from our Address__c geolocation field as parameters. We added the following method in the controller, which is called by a button on the page:


THE Google Maps Javascript API
If you really want to unleash the potential of Google Maps look no further than the Google Maps Javascript API.  Using the Javascript API allows you to wield much greater power and control over your maps behavior, adding layers of interaction and features unavailable through just the Embed API.
First let's improve on what we did earlier with the Embedded API -- let's now show all World__c records on the map in one go:

Let’s take a look at the code used to generate the above. 

(1.) The heart of the map functionality is generated in the initialize() function, called on window load. 
-MapOptions is used to specify characteristics of the map, in this case where to center the map (location of the current record) and the zoom level
-The div to be used to contain the map is specified — the API now knows where to put the map it generates





(2.) We want to show all the World__c records on the map, so we build a list of them (AllLocations property) in the new controller we created as follows:



-This simply gathers the relevant record properties (coordinates, name) and bundles them up to be used in the script.
-A marker is instantiated for each record and its coordinates are set



Reasonable enough.. But what about actually creating the World__c records? We will create an example where we can drop a pin anywhere in the world, and create a record in salesforce right then and there — from within the map! This is what it will look like:



We want to capture the event of the user clicking on the map, get those coordinates, and have the option to create a new record from the location the user clicked on. Here is what we added to the initialize() method in the page code used to accomplish all this: 


                       

There may seem like a lot is going on there so let’s take a closer look. 


(3.) There are a multitude of events that the API could potentially respond to, one of which is a click of the mouse on the map. We use an event listener here to capture the coordinates of the mouse click to help us build a record from it later.

(4.) We create a marker on the spot where the mouse was clicked. 
-We add a click listener on the marker so that we can show a popup dialog (called an infobox) 
-We define the infobox to have an input field, a button, and the lat/lng coordinates. We used the counter here to uniquely identify the infobox being used, as the user can add multiple pins to the map (and hence have multiple infoboxes in the DOM). For each marker added in this way, we increment the counter to keep track of the input field. 

(5.) Once the user clicks the save button in the infobox, we pass the latitude, longitude, and counter to a javascript method
- The method gets the value of the inputted name based on the counter passed to it (id of the element is a concatenation of “name” + “ counter” ex: “name4” for the 4th marker created this way
- Call a method in the controller to create the record with the coordinates and name specified : 

*The method is marked as global to allow it to be called from within the inline page

And voila! We have created a new record from the map! 




While this post only skimmed the surface of the APIs, we hope that it has set you in the right direction in beginning your own explorations of them. Try creating directions between records in your org by using a polyline, or adding record details to an infobox, perhaps an image roll.. There are any number of things you can do still that are fun to try and thankfully are also very well documented. 

Sep 4, 2014

Lab Coat Lesson: Sample SOQL Injection



As a Force.com developer, you're familiar with performing SOQL queries and how flexible and powerful they can be. As you're developing for your company or customers whether it be for just internal use or creating a Managed Package, you've probably read, heard, or learned the hard way (hopefully not that last one) that you want to avoid scenarios that create an entry point for SOQL injection.

SOQL injection exploits your code in a way that modifies and takes advantage of an expected input used in a part of your query to return more information than is normally asked for.

Here's a quick example: On the Visualforce page below, there is a table of Contact information for records where only Contacts with a LastName starting with a letter provided in the URL parameter "letter."


The URL includes: .../apex/SOQLInjection?letter=b

Take a look at the Apex method that queries for matching Contact records and returns the results:


Basically, whatever is in the URL parameter is fed into this line:

While it works like a charm, by accepting input directly from a URL parameter (exposed/visible to an end user or not), you're opening your code up to the possibility of injection.

What if we do exactly that? Here's one example of how you can update the URL to return ALL of the Contacts, even those not flagged as "Public":



The URL now includes:


Then ends up translating in your query to:

To remedy this, the primary best practice from Salesforce is to avoid dynamic queries whenever possible by using static queries and binding variables within those queries. If you can't get away from dynamic SOQL, you can make use of the string.escapeSingleQuotes method.

Let's modify our getter method to use the escapeSingleQuotes method:

Making this change will result in the following query string:

This query results in the user receiving 0 results: