Thursday, December 5, 2013

Getting around the five icon limit in the Google Static Maps API

Our application uses the Google Maps API, including the static maps API. We use custom icons for our markers to help make the maps better match our brand. In the live maps this isn't an issue and we can have as many custom markers as we like. But Google limits you to 5 custom icons in static maps, even with a business license. Most of our icons look roughly the same, they just have different numbers in them to function as our labels, so we quickly exceed that 5 icon limitation.

My methods for getting around this quickly evolved.

I started by not even knowing the limitation, by test case only had 5 icons, so it all seemed fine. In reality as soon as my users would have more than 5 my first 5 were custom and everything after that was the standard Google Map inverted teardrop marker with a dot in it. Not cool as it totally broke our branded look, and made the map look inconsistent.

Once the problem was realized I put a switch in. If 5 or less, use our branded icons, 6 or more, use all teardrops, with the label set to be number I need. This was better, as it was consistent at least, however; the map did not look great when framed with the style of our app when there were more than 5 icons. Furthermore the label property of the teardrop markers is limited to 1 character, so as soon as we had 10 icons it was back to having teardrops with dots in them, which are pretty useless for us.

So now I came up with the solution that probably attracted you to this post. I'm going to try to give it to you at a high level so that you can make it work with your language of preference, but any example are going to be in ColdFusion since that's what we use.


  1. You probably already know how, and depending on your source it's going to be different anyway, but collect up all your map data. Required bits are going to be: center point, zoom, map type, and output image size. I am going to assume sensor (if the application has access to GPS) is false. Also you are going to need all of your marker information which will include the icon you are going to use, and the geo coordinates of them.
  2. I POSTed this all to the CF page that is going to make all the magic happen.
  3. Map your first 5 points as normal. Get the results as a .png, ex1 below
  4. Map your next 5 points but add "style=feature:all|visibility:off" to the query string, get result as a .png. This will give you a png with a transparent background but will have all of your marker icons on it. It will be the same size as your initial map, and the markers will be placed correctly withing that rectangle. ex2 below.
  5. Watermark that image on top of your initial map. ex3 below, NOTE: this step is probably going to vary the most depending on your language of choice and what image manipulation features it offers.
  6. Repeat 4 and 5 until you have all of your markers.
  7. Write out you image with all of the markers now on it. ex4 below.

ex 1:


<cfhttp url="http://maps.googleapis.com/maps/api/staticmap" method="get" path="#PathWhereIWillStoreTempMapImages#" file="#TempMapImageFileName1#.png" getasbinary="yes">
 <cfhttpparam type="url" name="size" value="800x800">
 <cfhttpparam type="url" name="format" value="png">
 <cfhttpparam type="url" name="key" value="#MyGoogleAPIKey#">
 <cfhttpparam type="url" name="center" value="38.897701,-77.036527">
 <cfhttpparam type="url" name="zoom" value="15">
 <cfhttpparam type="url" name="maptype" value="roadmap">
 <cfhttpparam type="url" name="sensor" value="false">
 <cfhttpparam type="url" name="markers" value="icon:http://www.mywebsite.com/icon1.png|38.886839,-77.004743">
 <cfhttpparam type="url" name="markers" value="icon:http://www.mywebsite.com/icon2.png|38.903001,-77.018238">
 <cfhttpparam type="url" name="markers" value="icon:http://www.mywebsite.com/icon3.png|38.705634,-77.035854">
 <cfhttpparam type="url" name="markers" value="icon:http://www.mywebsite.com/icon4.png|38.886839,-77.004743">
 <cfhttpparam type="url" name="markers" value="icon:http://www.mywebsite.com/icon5.png|38.884658,-77.023684">
</cfhttp>


ex2:


<cfhttp url="http://maps.googleapis.com/maps/api/staticmap" method="get" path="#PathWhereIWillStoreTempMapImages#" file="#TempMapImageFileName2#.png" getasbinary="yes">
 <cfhttpparam type="url" name="size" value="800x800">
 <cfhttpparam type="url" name="format" value="png">
 <cfhttpparam type="url" name="key" value="#MyGoogleAPIKey#">
 <cfhttpparam type="url" name="center" value="38.897701,-77.036527">
 <cfhttpparam type="url" name="zoom" value="15">
 <cfhttpparam type="url" name="maptype" value="roadmap">
 <cfhttpparam type="url" name="sensor" value="false">
 <cfhttpparam type="url" name="markers" value="icon:http://www.mywebsite.com/icon6.png|39.023456,-77.054743">
 <cfhttpparam type="url" name="markers" value="icon:http://www.mywebsite.com/icon7.png|38.963001,-77.048238">
 <cfhttpparam type="url" name="markers" value="icon:http://www.mywebsite.com/icon8.png|38.755634,-77.055854">
 <cfhttpparam type="url" name="markers" value="icon:http://www.mywebsite.com/icon9.png|38.826839,-77.044743">
 <cfhttpparam type="url" name="markers" value="icon:http://www.mywebsite.com/icon10.png|38.814658,-77.033684">
 <cfhttpparam type="url" name="maptype" value="roadmap">
</cfhttp>


ex3:


<cfimage source="#PathWhereIWillStoreTempMapImages#/#TempMapImageFileName1#.png" name="layer_1">
<cfimage source="#PathWhereIWillStoreTempMapImages#/#TempMapImageFileName2#.png" name="layer_2">
<cfset ImagePaste(layer_0,layer_this,0,0)>


ex4:


<cfimage action="write" overwrite="yes" source="#layer_1#" destination="#PathWhereIWillStoreTempMapImages#/#TempMapImageFileName1#.png">


I reviewed the license and TOS for the static maps API, and I can't find anything about how this might be a violation. If it somehow is, please let me know and I will cease using this method and remove this post.