Time Estimate


Work with GeoJSON and Create the Map

Get the GeoJSON File

Next we need a GeoJSON file with zip codes matching (or at least overlapping with) the ones in the CSV file. There’s one all ready for you, which you can download from here.

Reformat the GeoJSON

GeoJSON comes to us in the standard format:

	"type": "FeatureCollection",
	"features": [{
		"type": "Feature",
		"properties": {
			"kind": "ZIP Code Tabulation Area (2012)",
			"external_id": "90001",
			"name": "90001",
			"slug": "90001-zip-code-tabulation-area-2012",
			"set": "/1.0/boundary-set/zip-code-tabulation-areas-2012/",
			"metadata": {
				"AWATER10": 0,
				"CLASSFP10": "B5",
				"ALAND10": 9071359,
				"INTPTLAT10": "+33.9740268",
				"FUNCSTAT10": "S",
				"ZCTA5CE10": "90001",
				"MTFCC10": "G6350",
				"GEOID10": "90001",
				"INTPTLON10": "-118.2495088"
			"resource_uri": "/1.0/boundary/90001-zip-code-tabulation-area-2012/"
		"geometry": {
			"type": "MultiPolygon",
			"coordinates": [
						[-118.265151, 33.970249],
						[-118.265166, 33.974735],
						[-118.262969, 33.974746],
						[-118.262981, 33.981836],
						[-118.265174, 33.981828],
						[-118.265185, 33.989227],
						[-118.256436, 33.989317],
						[-118.256436, 33.989498],
						[-118.241159, 33.989422],
						[-118.241126, 33.988174],
						[-118.240505, 33.988158],
						[-118.240502, 33.98867],
						[-118.23899, 33.988664],
						[-118.239021, 33.989403],
						[-118.237918, 33.989393],
						[-118.235685, 33.979486],
						[-118.235352, 33.979534],
						[-118.235105, 33.978705],
						[-118.234324, 33.974732],
						[-118.234685, 33.974731],
						[-118.234432, 33.972967],
						[-118.233915, 33.970674],
						[-118.233561, 33.970731],
						[-118.232835, 33.967469],
						[-118.232995, 33.967467],
						[-118.232405, 33.965314],
						[-118.231371, 33.963268],
						[-118.230013, 33.961768],
						[-118.231885, 33.961565],
						[-118.231599, 33.960146],
						[-118.237366, 33.960152],
						[-118.23737, 33.958521],
						[-118.237943, 33.958518],
						[-118.237949, 33.96015],
						[-118.24499, 33.960148],
						[-118.244994, 33.959648],
						[-118.246648, 33.959637],
						[-118.246653, 33.959177],
						[-118.247237, 33.959175],
						[-118.247225, 33.9597],
						[-118.253962, 33.959701],
						[-118.253959, 33.960162],
						[-118.258573, 33.96016],
						[-118.258575, 33.959577],
						[-118.260754, 33.959772],
						[-118.260753, 33.960149],
						[-118.265118, 33.96013],
						[-118.265139, 33.966482],
						[-118.264629, 33.966483],
						[-118.264607, 33.967438],
						[-118.265142, 33.967395],
						[-118.265151, 33.970249]
	}, ...]

Standard GeoJSON works well in most applications, but it’s problematic for custom maps in Analytics. The problem isn’t in displaying the map; it occurs when you try to display data using the map chart. That’s because Analytics looks for an ID at the same level as the "type": "Feature" node that matches an ID in the data. That’s how it knows to match a row from the CSV file to a particular zip-code area on the map. In fact, that ID property has to be named "id"!

In this example, the obvious ID to use is the zip code value itself. The fix is to move the key up one level, or just “flatten” the GeoJSON by moving everything under "properties" up one level. Get ready to use your coding skills!

  1. For the Los Angeles zip codes, create a script or use a fancy regular-expressions formula to move "external_id" up one level so it’s a child of "features".
  2. Be sure to rename the new key-value node "id".
    The value of each "id" will be a zip code, to match the zip codes in your dataset's Zipcode column.
  3. If your script outputs a file with a new name, note the name of the file and its location. You need them when you upload the GeoJSON to Analytics.

For example, here’s a quick-and-dirty Python script that creates the "id" node at the same level as "type":

                                import json
                                f = open('Downloads/test_la_zip_code_areas_2012.json', 'r')
                                json_contents = json.loads(f.read())
                                features = json_contents["features"]
                                for i in features:
                                    i["id"] = i["properties"]["external_id"]
                                # If shrinking the size of the file is important, 
                                # the properties node could be deleted afterwards:
                                # del i["properties"]
                                out_file = open("out_la_zip_code_areas_2012.json", "w")
                                # out_file will not be sorted, which shouldn't affect anything,
                                # but to have it be sorted, use sort_keys=True in json.dumps


The quick-and-dirty script shown above actually stripped the wrapper around the feature objects, so if you use it, restore the following:

                			"type": "FeatureCollection",
                			"features": {[
                			"comment" : "stuff that was output by the script goes here"

Now the GeoJSON looks something like this:

	"type": "FeatureCollection",
	"features": [{
		"type": "Feature",
		"properties": {
			"kind": "ZIP Code Tabulation Area (2012)",
			"external_id": "90001",
			"resource_uri": "/1.0/boundary/90001-zip-code-tabulation-area-2012/"
		"id": "90001",
		"geometry": {
			"type": "MultiPolygon",
			"coordinates": [
						[-118.265151, 33.970249],
	}, ...]

Every id has the value of the actual zip code in the feature object that it’s a part of. Don't try to use this GeoJSON snippet—it's just a small part of the output you'll get!

Upload the GeoJSON and Create the Map

In Analytics, you can use the same GeoJSON to create multiple maps, each with a different zoom factor or focus area. Before you can create a map, upload the GeoJSON to Analytics. In case you didn’t reformat your own GeoJSON file, use one that we’ve already reformatted for you.

  1. Right-click this link and save the reformatted GeoJSON file to your local machine.
  2. Log in to your Salesforce DE org, and navigate to the URL formed by appending /analytics/wave/web/custommap.apexp to your org’s base URL. For example, if your org’s base URL is https://na30.salesforce.com, go to https://na30.salesforce.com/analytics/wave/web/custommap.apexp.
  3. Click New.

    The insertion window for a new custom map appears. It has two sections, one for the GeoJSON and one for the map itself.

  4. Enter la_zip_codes in the GeoJSON Label and GeoJSON Name fields.

    The GeoJSON name and label appear in the custom-map administration screens.

  5. Click Choose File and select the reformatted GeoJSON file that you just downloaded.
  6. Click Insert and look for a confirmation message in the Results section of the insertion window.
    custom map geojson upload screen

    Now you can create the map.

  7. In the Map Label and Map Name fields, enter L.A. Zipcodes. The map name and label appear in Analytics.
  8. Select Equirectangular in the Projection field.

    Equirectangular is appropriate for simple geometric shapes such as zip-code areas.

  9. Select the GeoJSON definition you created, la_zip_codes, in the GeoJSON field.
  10. Click Insert Map and look for a confirmation message in the Results section of the insertion window.
    custom map insert map screen

Once you create the map, you can select it from the list of maps for the map chart in Analytics. It appears in Analytics like this:

custom map los angeles zip codes with no data

Congratulations! You’ve created your first custom map. And isn’t it a beauty!



If there’s something wrong with the GeoJSON file that you uploaded, an error message appears (something like “Invalid GeoJSON”) instead of the map. Usually that means something went wrong with the reformatting.

Explore the Data

When you created the Los Angeles zip-code dataset, you set the Zipcode column’s data type to dimension. This action makes it possible to group by zip code when you explore the data.

Now explore the zip-code data in a lens and view it on the map:

  1. From the Analytics home page, click the Datasets tab.
  2. Locate the zip-code dataset you created, then click it to explore it in a lens. initial lens view of los angeles zip-code tax data
  3. In the lens, click the Count of Rows measure, then Sum, then TotalWages to change the measure to Sum of TotalWages.
    Make sure to click the name of the measure you're changing, Count of Rows, in the Bar Length field.
  4. Click the plus button in the Bars field, then select Zipcode to group by zip code. los angeles zip-code tax data sum of total wages grouped by zip code
  5. Click button to clip lens to builder to open the step naming dialog.
  6. Enter Total Wages by Zip Code in the Display Label field, and click Clip to Designer to clip the lens to the dashboard designer.
  7. In the dashboard designer, drag the new step onto the canvas. Adjust the size of the widget as necessary to be able to view the bar chart that appears.
  8. From the Chart Type menu, select Map for the chart type, then close the menu.
  9. Expand the Map panel and select Custom: L. A. Zipcodes from the Map Type menu.
    An unimpressive map appears with several colored zip-code areas where Los Angeles is found (those flyspecks approximately in the central part of the visible coast). los angeles zip-code map with tax data
  10. Save the dashboard, naming it Los Angeles Tax Data by Zip Code.

The problem with this map is that it includes zip-code areas for all of Southern California, which means the Los Angeles area is much too small to be useful. We can fix that by creating a bounding box. We do that next.