Interactive Map Filtering
Overview
This tutorial walks you through building a Screen Flow in which a map and four metrics update in real time as the user pans or zooms. When the user moves the map, the visible records shrink or expand, and the metrics recalculate automatically to reflect what's on screen.
Consider using Dynamic Components for this tutorial
This tutorial still works, but building reactive map + metrics UIs is exactly what Dynamic Components are designed for. In DC, the Map's centerLatitude, centerLongitude, and visibleWidthKm plug directly into a Query filter — no formula variable, no text concatenation, and the queries re-run automatically as the user moves the map. Keep the Flow version only when this UI has to live inside a Screen Flow process.
What You'll Build
A single-screen flow with:
Four Avonni Metric components showing counts or sums for the visible area (for example: number of accounts, total revenue, number of active customers, average deal size).
An Avonni Map displaying records pinned by location.
Two Flow formula variables that act as live filters. Every time the user moves the map, the formulas recompute and the components re-query.

Before You Start
You need one of the following data setups. The tutorial uses the first option because it works on any Salesforce org without creating custom fields.
Standard Account with a billing address
Your Accounts need populated BillingStreet, BillingCity, and BillingCountry — or directly populated BillingLatitude and BillingLongitude. Salesforce auto-populates the lat/long via a Data Integration Rule ("Geocodes for Account Billing Address").
Custom object with a Geolocation field
Your object needs a field of type Geolocation (compound lat/long).
Standard object with two Number fields
Your object has a Latitude and Longitude number field, each with up to 15 decimal places.
Important
The DISTANCE() SOQL function used in this tutorial requires a compound location field — either a Geolocation custom field or a standard compound address like BillingAddress. It does not work against two separate Number fields. If your setup uses two separate lat/long numbers, see Adapt to Your Own Data
The rest of the tutorial uses the standard Account object with its built-in BillingAddress compound field and Industry picklist.
Step 3 — Configure the Four Metrics
Drag an Avonni Metric component into each of the four columns. Give each one a clear API Name so you can reference it later.
For every metric, do the following:
Open the Component Builder on the metric (click Edit on the component card).
In the Properties tab, set the Label — for example,
Total accounts in view.Expand the Primary section. This is where you configure the main metric value.
Set the Format Style to match what this metric displays:
Decimal — for counts or plain numbers (e.g., number of accounts, average employees).
Currency — for monetary values (e.g., total revenue).
Percent or Percent Fixed — for ratios and percentages.
Date — if the metric represents a date (e.g., most recent activity).
On the Value attribute, click the small icon on the right and select Query.
Choose the object — use Account for this tutorial.
Pick the field and aggregate function for that metric.
Optionally, add an Avatar icon from the Avatar section to give each metric a visual identifier.
Here's a suggested configuration for a realistic dashboard:
Total accounts in view
Decimal
COUNT
Id
Total accounts in view
Total annual revenue
Currency
SUM
AnnualRevenue
Revenue
Active customer count
Decimal
COUNT
Id + filter Active__c = true
Active
Average employee count
Decimal
AVG
NumberOfEmployees
Avg. employees
Example: A field sales rep drags the map over the Bay Area. The four metrics immediately show "47 Accounts", "$12.4M Revenue", "31 Active", "Avg. 218 employees" — all for the zone they're currently viewing
Step 4 — Add and Configure the Map
Drag an Avonni Map component below the section.
In the Properties tab, set Map Type to Leaflet Maps.
Important: Google Maps does not report the visible viewport back to Flow. Only Leaflet Maps exposes
centerLatitude,centerLongitude, andvisibleWidthKm— the values we need for dynamic filtering.In Data Source, choose Query and select the Account object.
In Data Mappings, connect:
Latitude →
BillingLatitudeLongitude →
BillingLongitude
Give the Map a clear API Name — this tutorial assumes
map. The formulas in Step 5 reference this name exactly.

Step 5 — Create the Dynamic Filter Formulas
This is the core of the tutorial. We'll create two Flow formula variables that produce a live SOQL filter clause. Each time the user moves the map, the formulas recompute and feed the Map and Metrics with a fresh filter.
Simpler using Avonni Dynamic Components
The Map's centerLatitude, centerLongitude, and visibleWidthKm plug directly into a Query filter — no formula variable, no text concatenation.
Formula 1 — Map Filter
This formula controls which records appear as pins on the map.
In the Flow toolbox, create a new Formula resource.
Name it
VisibleAreaFilter, with Data Type set to Text.Paste this expression:
"DISTANCE(BillingAddress, GEOLOCATION(" & {!map.centerLatitude} & "," & {!map.centerLongitude} & "), 'km') <" & TEXT({!map.visibleWidthKm})

What each piece does:
"DISTANCE(BillingAddress, GEOLOCATION("
Start of the SOQL clause. BillingAddress is the compound field containing the record's location.
& {!map.centerLatitude} & "," & {!map.centerLongitude}
Injects the map's current center coordinates, live.
& "), 'km') <"
Closes the GEOLOCATION and DISTANCE calls, units in kilometers.
& TEXT({!map.visibleWidthKm})
Converts the map's current visible width (in km) to text and appends it as the comparison threshold.
The & "&" syntax is standard Flow text concatenation — each & glues the surrounding pieces together, and TEXT(…) converts numbers to strings so they sit cleanly inside the SOQL string.
Formula 2 — Metric Filter
Some of your metrics show the full visible population — every Account on the map. These metrics can be reused VisibleAreaFilter as-is. But some metrics measure a subset of what's visible — only active customers, only a specific industry, only high-revenue accounts. For each subset, you need a separate formula that layers an extra SOQL condition on top of VisibleAreaFilter.
When to create a segment filter:
✅ Create one when the metric answers "how many of the visible records also match X condition?"
❌ Skip it when the metric answers "what's the total / count / average of everything visible?"
For the four metrics in this tutorial, here's how the mapping works:
Total accounts in view
No — counts everything visible
VisibleAreaFilter
Total annual revenue
No — sums everything visible
VisibleAreaFilter
Active customer count
Yes — only active accounts
MetricFilterActive (new formula)
Average employee count
No — averages everything visible
VisibleAreaFilter
Create the segment filter formula:
In the Flow toolbox, create a new Formula resource.
Name it
MetricFilterActive, with Data Type set to Text.Paste:
"DISTANCE(BillingAddress, GEOLOCATION(" & {!map.centerLatitude} & "," & {!map.centerLongitude} & "), 'km') <" & TEXT({!map.visibleWidthKm}) & " AND Active__c = true"
The added " AND Active__c = true" at the end narrows results to active accounts only. The rest of the expression is identical to VisibleAreaFilter — same distance calculation, same visible-width comparison.
Create one formula per segment you want to track:
Active accounts
AND Active__c = true
Technology accounts
AND Industry = 'Technology'
Large accounts ($10M+)
AND AnnualRevenue > 10000000
Accounts with open opportunities
AND Id IN (SELECT AccountId FROM Opportunity WHERE IsClosed = false)
Tip: Keep formula names descriptive of the segment, not of the metric —
MetricFilterActiveis reusable across any metric counting active records, whileActiveCustomerCountFilteris not.
Step 6 — Wire the Formulas as Mapped Filters
Connect each formula to the right Metric. The Map itself doesn't need a filter — Leaflet automatically displays only the pins inside the current viewport, and filtering the Map's query on top of that would break the user's ability to pan smoothly into adjacent areas.
For each Metric:
Open the Metric's Component Builder.
Expand the Data Source section inside the Primary value.
In the Filter field, click the toggle and choose Mapped.
Select the formula that matches the metric:
Total accounts in view
VisibleAreaFilter
Total annual revenue
VisibleAreaFilter
Active customer count
MetricFilterActive
Average employee count
VisibleAreaFilter

Tip: If you need a Metric to count only what's on screen, use
VisibleAreaFilter. If you need a Metric to count a segment of what's on screen (only active, only a specific industry), use the dedicated segment filter you created in Step 5.
Step 7 — Test the Flow
Save and debug the flow.
When the flow opens, the map should load with all Account pins visible.
Zoom in or pan the map. The pins should be reduced to only those within the visible area, and the four metrics should update.
Zoom back out — pins and metrics should expand to match.
Tip: If the metrics show zero at first and only update after you interact with the map, that's normal —
centerLatitudeandcenterLongitudepopulate once the map has rendered its first view.
Adapt to Your Own Data
The tutorial uses Account.BillingAddress and Industry because every Salesforce org has them. If you want to use your own object or custom fields, here's what to change.
If Your Object Uses a Custom Geolocation Field
Replace BillingAddress in both formulas with your field's API name.
Example: A
Store__ccustom object with aStoreLocation__cGeolocation field:
"DISTANCE(StoreLocation__c, GEOLOCATION(" & {!map.centerLatitude} & "," & {!map.centerLongitude} & "), 'km') <" & TEXT({!map.visibleWidthKm})
Make sure:
The field type in Setup is Geolocation (not two separate Number fields).
You select Decimal coordinates with sufficient precision (at least 5 decimal places).
If Your Object Has Only Two Separate Lat/Long Number Fields
DISTANCE() in SOQL does not accept two separate numeric fields. You have two options:
Preferred: Add a Geolocation custom field to your object, and populate it from your existing lat/long fields (for example, via a Flow, a Batch Apex job, or a Data Loader update).
Alternative: Replace
DISTANCE()with a bounding-box filter. Instead of a radius check, filter records where latitude is between centerLat − visibleWidthKm÷111 and centerLat + visibleWidthKm÷111, and longitude similarly. This is less accurate at the poles but doesn't require a Geolocation field.
If Your Addresses Don't Have Lat/Long Values Yet
Salesforce can auto-geocode standard address fields. To enable it:
Go to Setup → Data Integration Rules.
Activate Geocodes for Account Billing Address (or the equivalent rule for your object).
Click Edit Rule Settings, then Run Rule Now to backfill existing records.
Once the rule runs, BillingLatitude and BillingLongitude populate automatically on every record whose address Salesforce can resolve.
If You Want the Metrics to Show Something Other Than Account Data
Swap two things in each Metric's configuration:
In the Metric's Data Source, change the queried object.
Update the corresponding formula variable's SOQL fragment to use the new object's location field. Remember that
DISTANCE()only works on that object's geolocation field, so the Map and the Metrics must query objects that both have location fields — or you'll need separate formulas per object.
Why does the metric sometimes count more accounts than visible pins?
The metric uses a circular radius based on the map's visible width. A few accounts just outside the visible rectangle may fall inside that circle. Pan or zoom out to see them appear.
Troubleshooting
Map loads but no pins appear
BillingLatitude/BillingLongitude are empty on your Accounts.
Activate the Data Integration Rule Geocodes for Account Billing Address in Setup and run the backfill.
Metrics show zero when the flow opens
The map hasn't published centerLatitude/centerLongitude yet — the formula evaluates against null on the first render.
Normal behavior. Interact with the map once (pan or zoom) to trigger the first recalculation. If this is a problem, wrap the formula in an IF that returns a default filter when the map center is empty.
Cannot read properties of undefined (reading 'match') at runtime
The formula produced an incomplete SOQL string — usually caused by a missing quote, a trailing &, or a reference to a map property that doesn't exist (wrong API name).
Copy the formula exactly from this tutorial, double-check the map's API Name matches the name used in the formula, and verify every & has text on both sides.
The filter works for the Map but not the Metric
The Metric is using the wrong formula — it's pointing at VisibleAreaFilter instead of MetricFilterTechnology (or vice versa).
In the Metric's Component Builder, confirm Data Source → Filter → Mapped points to the formula with the extra AND ... condition you want.
Setting Map Type to Google Maps breaks everything
Google Maps does not expose centerLatitude, centerLongitude, or visibleWidthKm back to Flow.
Switch to Leaflet Maps in the Map's Properties tab. This tutorial only works with Leaflet.
Pins appear but the metric count doesn't match the visible pins
The Metric formula has a different AND clause than the Map formula — that's expected if you want the metric to count a subset (like only Technology accounts).
To have the metric exactly match the visible pins, reuse VisibleAreaFilter instead of a custom one.
Metric count higher than visible pins
The radius filter is circular, the viewport is rectangular
Expected behavior — pan/zoom to reveal the extra accounts, or divide visibleWidthKm by 2 in the formulas for a tighter match
Last updated
Was this helpful?


