Skip to main content
Build the future with Agentforce at TDX in San Francisco or on Salesforce+ on March 5–6. Register now.

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 ready for you, which you can download 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 CRM Analytics. The problem isn’t in displaying the map; it occurs when you try to display data using the map chart. That’s because CRM 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. Let’s use our coding skills to see how we might accomplish this!

  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".

                #!/usr/bin/python
                import json
                import os
                os.chdir(os.path.expanduser('~/Downloads'))
                # standard geojson file
                f = open('test_la_zip_code_areas_2012.geojson', 'r')
                json_contents = json.loads(f.read())
                features = json_contents["features"]
                for i in features:
                    i["id"] = i["properties"]["external_id"]
                json_contents["features"] = features
                # Normalized geojson for Tableau map
                out_file = open("out_la_zip_code_areas_2012.json", "w")
                out_file.write(json.dumps(json_contents))
                out_file.close()
Note

The quick-and-dirty script shown above strips 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!

Display the Data in a Custom Map

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. After you group the data by zip code, you’ll visualize it in a custom map that shows L.A. zip codes. You’ll have to create the custom map based on a geoJSON file.

Let’s explore the zip code data in a lens and view it on the custom map.

  1. On the Analytics Studio home page, click Browse and type la_zip_codes in the Search bar.
  2. Click the dataset from the search results 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. To change the chart type to a map, click Formatting button on the right and select the Map chart type (Map chart type button). The default map doesn’t show L.A. zip codes and therefore isn’t a good map for this data. Actually, none of the prebuilt map types can show data grouped by zip codes. Let’s create a custom map that can.
  6. To create a custom map type, click Formatting button, expand the Map section, and then Add Map button next to the Map Type property. The Add button for custom maps.
  7. In case you didn’t reformat your own GeoJSON file, we’ve reformatted one for you. Right-click this link and save the reformatted GeoJSON file to your local machine.
  8. In the left pane of the New Map page, click Upload GeoJSON and upload the GeoJSON definition (custom_map_project_geojson.json) that you downloaded.

    Select the geoJSON file, boundaries, label, and projection type for the new map. Note If there’s something wrong with the GeoJSON file that you uploaded, an error message appears (something like “Invalid GeoJSON”). Usually that means something went wrong with the reformatting.
  9. In the Map Label field, enter L.A. Zipcodes.
  10. In the Projection Type field, select Equirectangular as the default projection type for this map. You can override this setting in the widget properties for each chart widget that uses this custom map. Equirectangular is appropriate for simple geometric shapes such as floor plans, city blocks, or zip-code areas. Mercator is most suitable for traditional geographical maps. Use AlbersUSA for a map of the United States of America that includes Hawaii and Alaska near the rest of the United States. The L.A. map appears using the equirectangular projection. Note In the center pane, you could drag the handles of the map to change the boundaries, and zoom in on a particular region. The boundaries would show in the right pane. However, we won’t change the boundaries yet. We’ll look at them in more detail in a bit.
  11. Click Done. Congratulations! You’ve created your first custom map. And isn’t it a beauty! You can now use this custom map type in other charts, including map, geo map, and bubble map charts.
  12. To clip this lens to a dashboard in designer, click button to clip lens to builder.
  13. In the query naming dialog, enter Total Wages by Zip Code in the Display Label field, and click Clip to Designer.
  14. In the dashboard designer, drag the new query onto the canvas. Adjust the size of the widget as necessary to be able to view the bar chart that appears. 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). The widget appears.
  15. Select the map to display the widget properties.
  16. In the widget properties, expand the Map section and notice that the new L. A. Zipcodes custom map is selected in the Map Type menu. los angeles zip-code map with tax data
  17. 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.

Share your Trailhead feedback over on Salesforce Help.

We'd love to hear about your experience with Trailhead - you can now access the new feedback form anytime from the Salesforce Help site.

Learn More Continue to Share Feedback