Skip to main content

Map

How to embed, configure, and use the Mosaic Map component.

Overview

Mosaic is a Salesforce-native geospatial mapping platform built around two components:

  • Mosaic: Map: the map itself. Drop it on any App Page, Record Page, or Experience Cloud page and point it at a configured map.
  • Mosaic: Map Preview: a dropdown selector that lists every map in your org and embeds the chosen one. Useful for an "explore everything" landing page.

A "map" in Mosaic isn't built in code. It's assembled from records. You define layers (points or regions), populate them with bytes (individual features), and link them to a map via settings records. The map reads that configuration at runtime and renders the result.

End users get search, filters, bookmarks, dark/light themes, and inline editing out of the box. The map also handles clustering, popovers, runtime CSV and GeoJSON uploads, Google Places search, and AI-assisted address parsing.

You can also build a map with no data prep at all: pull boundaries for the area you are looking at straight from the US Census, join published health statistics onto them, or fill regions by counting the points that fall in them. Those are covered in Adding boundaries and Filling regions from a point layer.


Adding the Map to a Page

  1. In App Builder, drag Mosaic: Map onto your page layout.
  2. Set the Map Unique Name property to match a map you've configured in records (see Configuring a Map).
  3. Optionally set Style Configurations to a JSON string for sizing (e.g. {"height": "80vh", "minHeight": "400px"}).
  4. Save and Activate.

To let users pick which map to load, use Mosaic: Map Preview instead. It shows a dropdown of every configured map and renders the selected one. Available on App Pages only.

Note: If the map component has no explicit height and its parent container doesn't define one either, the map will collapse. Always set a height somewhere, either in Style Configurations or on the parent container.


Configuring a Map

A map is a collection of layers grouped under a shared Map Unique Name. The entire setup is record-based: no code, no deployment.

1. Assign the Permission Set

Grant the Mosaic Admin permission set to anyone who needs to manage maps and layers. End users only need read access on the underlying data; they don't need this permission set to view a map.

2. Configure Flourish API Credentials

Map tiles and Google Places need no configuration. Those credentials ship with the package and are managed by Flourish, so there is nothing to obtain, enter, or rotate. Tiles render and place search works as soon as the package is installed.

The one thing you do set is your own Flourish API credentials. Open the FL Mosaic custom metadata type, create a record named global (or update the existing one), and fill in FL API Token, FL API Org and FL API Env. Flourish issues these during onboarding.

They are needed for two things: uploading a GeoJSON boundary file through the map, and AI-assisted address parsing. Everything else on the map works without them.

3. Create One or More Layers

Open the Mosaic Layers tab and create a Mosaic Layer record for each layer you need. See Layers for full details on geometry types, recall types, and field reference.

Open the Mosaic Settings tab. For each layer in the map, create a new Mosaic Setting:

FieldValue
Map Unique NameYour chosen identifier (e.g. customer-overview). Use this same value when placing the component on a page.
TypeComponent
Keylayer
LayerLook up the Mosaic Layer to include.

Optionally add another row with Type blank, Key = label, and Value = the human-readable map name. The Map Preview dropdown reads this label.

That's it. Drop Mosaic: Map on a page, set Map Unique Name to customer-overview, and the map renders.


Layers

Two axes drive a layer's behavior: what it renders (Geometry Type) and where its data comes from (Recall Type).

Geometry Type

ValueRenders as
PointMarkers (clustered automatically when zoomed out).
RegionPolygon overlays from a GeoJSON file.

Recall Type

ValueBest forTrade-offs
BytesCurated, relatively static data; large volumesFaster load; data lives in Mosaic Byte records. Required if you want users to add points at runtime.
QueryLive Salesforce records (Accounts, Contacts, Cases, etc.)Always current; bound by SOQL row limits and query performance. Read-only from the map UI.

Layer Fields Reference

FieldApplies toDescription
NameAllDisplay name in the legend.
Unique NameAllStable external key. Auto-generated for layers created from runtime uploads.
Geometry TypeAllPoint or Region.
Recall TypeAllBytes or Query.
Point Icon URLPointPublic URL to the marker icon (PNG or SVG).
Point Popover VariantPointFields, Chronicle, or Google Search. See Point Popovers.
Point Popover ConfigsPointJSON config. For Chronicle: {"templateId": "<id>"}.
Point ConfigsPointJSON for advanced point options.
Region GeoJSON URLRegionPublicly accessible GeoJSON FeatureCollection.
Region ID PropertyRegionProperty in the GeoJSON properties block that joins to the Byte's Region ID field.
Region ID Label / Region Value LabelRegionFriendly labels (e.g. "Zip Code", "Population"). The ID label prefixes the hover tooltip; together they title the legend ("Population Density by Zip Code").
Region Color MapRegionJSON color scale: categorical, graduated, or continuous. See Region Coloring.
Query SObject NameQueryThe Salesforce object to query (e.g. Account, Contact).
Query WhereQueryA SOQL WHERE clause without the keyword (e.g. Type = 'Customer').
Query Lat / Query LngQuery, pointsAPI names of the lat/lng fields on the source object.
Query Region Id / Query Region ValueQuery, regionsAPI names of the region-id and value fields.
Query Metadata FieldsQueryComma-separated API names, or * to include every field on the object.

Tip: Setting Query Metadata Fields to * is a quick way to surface everything in the popover without listing fields by hand. Address/Location field groups, Id, and CreatedDate are filtered out automatically.


The Regions & Points panel

Everything on the map is managed from one panel in the side nav, with regions above and points below.

Each row carries the layer's name, a color chip showing its scale at a glance, and the number of features in it. Clicking the row's icon toggles the layer on and off.

Regions additionally offer:

  • A caret that expands the row. Inside is the layer's color ramp with its range at either end, a summary of how the scale was built, and an opacity slider. Dragging the slider restyles the layer live rather than reloading it.
  • Drag to reorder. Region layers draw in panel order, so drag a row to put one on top of another. This is how you show a small set of regions over a larger one.
  • An action menu with Save to Salesforce, Fill from a point layer, and Remove for a session layer.

Points offer a filter funnel (see Filters), the same action menu, and Toggle all in the section header to switch every point layer at once.

The two upload icons in the section headers are the way in to runtime uploads and boundaries.


Region Coloring

A region takes its color from one of two places:

  1. The layer's color scale: the Region Color Map field on the Mosaic Layer record. This is a rule applied to every region, and it's what generates the legend.
  2. The region's own color: the Color field on the Mosaic Byte record, which is also what the color property in an uploaded GeoJSON writes.

The scale wins where it has an opinion. Configuring one is a deliberate act taken at the layer level, so it governs. Per-region colors are the fallback for layers colored one region at a time. A region matched by neither draws transparent.

Scale Types

Categorical: a value maps to a color. Use it for groupings such as territories, status, or tiers.

{
"type": "categorical",
"property": "region",
"stops": [
{ "value": "North", "color": "#2E86AB", "label": "Northern" },
{ "value": "South", "color": "#C0392B", "label": "Southern" }
],
"other": "#DDDDDD"
}

Graduated: numeric ranges map to colors. Bounds are ascending and inclusive, the first match wins, and an upperBound of null catches everything above the last bin.

{
"type": "graduated",
"property": "density",
"stops": [
{ "upperBound": 10, "color": "#001100" },
{ "upperBound": 20, "color": "#002200" },
{ "upperBound": null, "color": "#003300", "label": "20+" }
]
}

Continuous: a smooth ramp between two or more colors across a numeric domain. Values outside the domain clamp to its ends.

{
"type": "continuous",
"property": "density",
"domain": [0, 5000],
"range": ["#F7FBFF", "#6BAED6", "#08306B"]
}

Tiled: no value at all. Adjacent regions are given different colors so you can tell them apart, the way a political map is colored.

{ "type": "tiled" }

Use it when the point is the shape of the regions rather than anything they measure: council districts, sales territories, school catchments. Mosaic works out which regions share a border and colors neighbors differently. A tiled layer draws no legend, because there is nothing to explain.

It is also the answer when a categorical scale has too many values. Categorical coloring covers eight distinct values; past that, regions stop being distinguishable and tiling is what you actually wanted.

Where the Value Comes From

property names a field in the region's Metadata. Omit it and the scale reads the byte's Region Value instead, which is what Query-mode layers populate from Query Region Value. So a Query layer plus a graduated scale gives you a live choropleth with no data entry at all.

Colors are computed when the map draws, never stored. Editing a scale recolors the map on the next load without touching a single record.

Note: A bare array, [{"upperBound": 10, "color": "#001100"}], is read as a graduated scale, so color maps written against the older format keep working.

The Legend

Active region layers appear in a collapsible legend at the bottom right of the map, titled from Region Value Label and Region ID Label. Categorical and graduated scales render as labeled swatches; continuous scales render as a gradient bar with its domain at either end. Graduated labels are derived from the bounds (Up to 10, 10 - 20, 20+) unless a stop sets its own label.

Layers with no scale name each swatch after the regions carrying that color, such as 77002, or NE, NW, SE. That's what you want when a file colors regions individually. Once a color covers more than three regions the label becomes a count instead, and past a dozen distinct colors the layer drops out of the legend entirely, where unlabeled swatches stop being informative.


Loading Data

There are two ways to populate a Bytes-mode layer: bulk-load Mosaic Byte records directly, or upload data at runtime through the map UI.

Mosaic Byte Fields

FieldRequiredDescription
LayerYesMaster-detail to the parent layer.
Lat / LngPointsCoordinates.
Region IdRegionsJoins to a feature in the layer's GeoJSON.
Region ValueRegionsDrives choropleth coloring through the layer's color map.
ColorNoHex color override for an individual feature.
LabelNoAuto-generated if blank. Shown in the popover header and search results.
UUIDNoAuto-generated when the record is saved.
MetadataNoJSON payload that drives the popover, search index, and filter property list.

Metadata Format

The Metadata field accepts two formats:

Object format: keys become field names. The popover auto-humanizes them for display (e.g. Billing_Street__c → "Billing Street").

{
"Name": "Acme Corp",
"Industry": "Tech",
"Billing_Street__c": "100 Main St"
}

Array format: use this when you want explicit display labels or need to declare data types so the popover picks the right input control.

[
{ "name": "Name", "label": "Company Name", "value": "Acme Corp" },
{ "name": "Website", "label": "Site", "value": "https://acme.com", "apexDataType": "URL" }
]

Runtime Uploads

The fastest way to bulk-load data is the upload modal. From the Regions & Points panel, click the upload icon next to Points or Regions.

Points require a CSV with Lat and Lng columns. Every other column becomes searchable/filterable metadata.

Regions require a GeoJSON FeatureCollection (.geojson or .json). Once loaded, pick the Region ID property that uniquely identifies each feature, and optionally provide a Region ID label for display (e.g. "Zip Code", "County Name").

Newly uploaded layers are marked Session: they belong to the browser rather than to the org. The browser keeps them, so a refresh brings them back with their colors and opacity intact, but nothing is in Salesforce and nobody else can see them. To make a layer real, open its action menu and choose Save to Salesforce.

Clearing your browser data discards session layers. It never affects anything already saved.


Adding boundaries

You do not have to find a GeoJSON file to map regions. Add boundaries for this area (the pin icon beside Regions in the Regions & Points panel) pulls them straight from the US Census.

  1. Pan and zoom to the area you care about. The fetch covers what is on screen, so the map view is the scope.
  2. Open the panel's boundary tool and pick a Boundary type.
  3. Click the fetch button. The regions arrive as a session layer, ready to color.

Boundary types include States, Counties, ZIP Codes (ZCTA), Census Tracts, Block Groups, Incorporated Places, Congressional Districts, State Legislative Districts, Unified School Districts, Metropolitan Statistical Areas, Urban Areas and Federal American Indian Reservations.

Each type has a minimum zoom, and it refuses rather than truncates. Zoomed out too far, a request for census tracts would cover more of the country than any one response can carry, so you would get an arbitrary slice with no way to tell which. Mosaic asks you to zoom in instead. Broad types like States work at any zoom; the finer the boundary, the closer in you need to be.

This covers the United States only.

Joining published statistics

Once you have a boundary set, Add data joins published figures onto it, keyed on the region's own census identifier.

The source that ships is CDC PLACES: model-based local health estimates covering around 40 measures, each a percentage of adults. Pick as many Measures as you want from the picker and fetch them.

Each measure arrives as a property on every region, which means it immediately becomes:

  • an option under Color by, so a choropleth is one more click,
  • a row in the region's popover,
  • a property you can filter and search on.

Nothing downstream treats it differently from a value you loaded yourself.

Two things worth knowing. The estimates are modeled, not counted, so they describe a small area's likely rate rather than a measured one. And coverage is uneven: a measure can come back empty across a whole area while its neighbors in the list are complete, which is the data's own gap rather than a failed fetch.


Filling regions from a point layer

A region layer can take its values from a point layer instead of from stored data. That turns any set of Salesforce records into a choropleth with no data entry.

Open a region layer's action menu and choose Fill from a point layer. Pick the point layer to count, and how to combine it: a count of records per region, or a sum, average, minimum or maximum of one of their numeric fields.

The result is written onto the regions as their value, so the color scale, the legend and the region values panel all read it with no extra configuration.

It follows your filters. The rollup counts the points that are actually on the map, so filtering the point layer recolors the regions to match. That is the feature, not a side effect: filter to this year's cases and the map redraws as this year's map.

A region that no point matched is a real zero when counting or summing, and blank when averaging. An average of nothing is not zero.


Point Popovers

Clicking a point opens a details popover. The header shows a contextual action bar; the body renders one of three variants determined by the layer's Point Popover Variant field.

Action Bar

Buttons appear based on context:

ButtonShown when
Go to RecordMetadata contains an Id field. Opens the Salesforce record in a new tab.
Edit / DoneVariant is Fields. Toggles inline edit mode.
Save as AccountVariant is Google Search. Creates an Account from the place data.
Add to LayerVariant is Google Search. Saves the place as a point on a Bytes-mode layer.
Google MapsVariant is Google Search and a place_id is present. Opens the place on Google Maps.

Variants

VariantUse whenNotes
FieldsDefault: auto-renders metadata as a formField types are inferred from apexDataType first, then value heuristics (URLs become links, numbers right-align, booleans become toggles, long strings become textareas). Click Edit to modify values; saves persist back to Salesforce.
ChronicleYou have a Chronicle form template to embedSet {"templateId": "<id>"} in Point Popover Configs. Form fields are prefilled from the point's metadata.
Google SearchSurface external Google Places resultsReserved for points sourced from POI search. Displays Categories, Business Status, and "Open Now" when available.

Inline Editing

In the Fields variant, click Edit to flip every field into edit mode. Change values, then click Done. Only changed fields are sent back to Salesforce. The update applies to the byte's metadata, the search index, and the filter property cache automatically.


Mosaic offers two complementary search surfaces.

Searches across:

  1. Your data: full-text match against label and metadata for every loaded layer.
  2. Google Places: included automatically when the "Always include Google Places" toggle is on; otherwise available on demand via the "Search Google Places for…" link in the dropdown.

Clicking a result from your data flies the map to it and opens its popover. Clicking a Google result drops a yellow marker, flies to the location, and opens the Google Search popover. From there you can save it as an Account or add it to a layer.

Search Panel (Side Nav)

Three sub-features:

  • Places of Interest: type a keyword (e.g. "churches", "schools") and press Enter to query Google Places in the current map view. Results appear as a dismissible POI layer with yellow markers.
  • Regions & Points: pick a dataset, optionally scope to a single property, type a keyword, and press Enter. Each search becomes a pill at the bottom; click between pills to switch result sets.
  • Search Settings: toggle "Always include Google Places in search bar results."

Filters

Each point layer with metadata properties exposes a filter funnel icon. Click it to open the filter panel for that layer.

A filter clause has three parts:

  1. Property: any metadata field on the layer.
  2. Operator: typed by property: text gets equals / contains / starts with; numbers get greater than / less than; dates get before / after; and so on.
  3. Value: skipped for value-less operators like is blank.

Click Add Filter to apply. Filter pills appear below. Click a pill to toggle it on/off without deleting, or click the X to remove it.

If other layers share the same properties, an Apply these filters to other layers section lets you check boxes and apply the active filter set to those layers in one click.


Bookmarks

Bookmarks let users collect points and regions across layers into named sets for later review.

  1. In the Bookmarks panel, type a name and click + to create a set. New sets start as Session (in-memory only).
  2. With the set focused, hold the B key and click points or regions on the map to add them. Click again to remove.
  3. Toggle Only show bookmarked items to hide everything else from the map view.
  4. Click Save Set to persist to Salesforce, or Delete Set to discard.

Saved bookmark sets persist across sessions and remain available the next time the map is opened.

Note: The B-key shortcut requires a focused set. Open the Bookmarks panel and click a set first; otherwise B+click won't do anything.


Settings

The Settings panel exposes user-adjustable preferences.

SettingEffect
ThemeSwitches the basemap style (light, dark, satellite, depending on what's enabled in your Mapbox account).
Toggle FullscreenExpands the map to fill the browser viewport.

The pin button on the map overlay saves the current center and zoom as the default starting view. Each user's pinned location is saved per-user, so different users can have different home views on the same map.


Map Preferences (Admin)

User-facing preferences are saved as Mosaic Settings records. Mosaic recognizes the following preference keys:

KeyValueEffect
label"Customer Overview"Display name in the Map Preview dropdown.
mapTheme"light", "dark", etc.Default basemap style.
defaultMapStart{"lat": 29.76, "lng": -95.37, "zoom": 11}Default center and zoom on load.
bookmarks(managed by the app)User-saved bookmark sets.
includeGoogleSearch"true" / "false"Whether top-bar searches always include Google Places.

Most preferences are written automatically when users change settings or pin a location. Edit them manually only when seeding initial state for new maps.


Time Series

Any layer carrying a date can be charted over time, and then played back across the map.

Open the Time Series panel in the side nav and build a series: pick the layer, the date field to bucket on, how wide a bucket is (day, week or month), and what to measure (a count of records, or a sum or average of one of their fields). The series is added to the panel.

A series is something you keep, not a mode the panel is in. Built series stay in the list, each remembering how it was defined and what it aggregated to, so moving between them redraws rather than recomputes. Build one per question and switch.

Clicking a series draws its timeline along the bottom of the map. Clicking a bucket on the chart narrows the map to that bucket.

Playback

The play control on a series row steps through the buckets in order, redrawing the map on each one. The row's count column shows the frame position as it runs, so you can see how far through it is and how many buckets there are.

Playback narrows what is already on screen; it does not replace it. A time window composes on top of your active filters, so filtering to one region and then playing a series animates that region rather than reopening the whole map. Pausing leaves the map on the frame you stopped at.

Because everything downstream follows what is visible, a playback frame plus a region rollup plus a color scale is an animated choropleth: the regions recolor on every frame as the points inside them change.

Filters and series

A series re-aggregates when the layer it was built from is filtered, so the chart always agrees with the map. That applies to every series built on that layer, not just the one on screen.


Keyboard Shortcuts

ShortcutAction
B + clickAdd or remove a point/region from the focused bookmark set

Troubleshooting

The map renders but no layers appear. Confirm at least one Mosaic Setting exists with Type = Component, Key = layer, a matching Map Unique Name, and a Layer lookup to a published Mosaic Layer.

A point's popover shows raw JSON. The Metadata field is probably an unstructured string. Save it as a proper JSON object or array, or set the layer's Point Popover Variant to Fields so the auto-renderer can display it properly.

My session layer is gone. Session layers belong to the browser, so they survive a refresh but not clearing your browser data, and they never appear for anyone else. Use the layer's action menu → Save to Salesforce to make one permanent.

The map won't load tiles. Tile credentials ship with the package, so there is no key to check. Confirm that api.mapbox.com is allowed in Remote Site Settings and CSP Trusted Sites, which the package also installs; a blocked host is the usual cause.

Google Places search returns nothing. The Places credentials ship with the package too. Mosaic surfaces Google's own error message in the toast, so read that first. Otherwise confirm the Google host is allowed in Remote Site Settings and CSP Trusted Sites.

I can't find the Mapbox or Google API Key fields. They are no longer yours to set. Both moved into the package, where Flourish manages and rotates them, so the fields are not visible in your org and nothing needs configuring. The only credentials you enter are the Flourish API ones, covered in Configuring a Map.

"Zoom in to load this boundary type." Finer boundary types need a closer view, because the area on screen would otherwise hold more regions than one fetch returns. Zoom in and try again, or pick a broader type.

A CDC measure came back empty for the whole area. Coverage is uneven by measure and geography. An empty result for one measure while others are complete is a gap in the published data rather than a failure.

"Add to Layer" doesn't show my layer. Only Bytes-mode point layers can accept new points from the Google Search popover. Query-mode layers are read-only. Change the target layer's Recall Type to Bytes, or pick a different layer.

"Save as Account" failed. The acting user needs Create permission on the Account object. The Mosaic Admin permission set covers map configuration but not necessarily Account creation in your org.

Top-search-bar Google results have a different label than POI panel results. When you click a single result from the top dropdown, Mosaic uses that result's name as the layer label. When you run a multi-result POI search from the side panel, the layer is named after the search query, because the result set may contain many places.

The B-key shortcut isn't adding bookmarks. Open the Bookmarks panel and click a set first to focus it. B+click only works when a set is focused.


Embedding a Map on a Website

A map can run on a page outside Salesforce: an intranet page, a partner portal, a member site. The map itself still runs in Salesforce, framed by a small script you paste into the host page.

What you need first

An Experience Cloud page carrying the Mosaic: Map component, with nothing else on it. This is the page the script frames, and its URL is what you paste into the snippet. Give it a height, as any page holding the map needs one.

Visitors have to sign in to that Experience site. Everything the map does, including its searches and its uploads, runs as the person viewing it, so the page has to know who that is. Point the snippet at a page that requires a login, not at a public guest page.

The snippet

<!-- Flourish Mosaic Map -->
<script src="https://cdn.toflourish.org/mosaic/v1/map-embed.js"
data-embed-url="https://yourorg.my.site.com/mosaic/embed"
data-map="community_resources"
data-max-width="960" defer></script>

The map is drawn where the tag sits, so paste it where you want the map to appear. There is no floating or corner mode: a map is content, and it belongs at the size the page chose.

All of the widget logic lives in the hosted script, so fixes reach embedded sites without anyone re-pasting a snippet. Stay on the /v1/ in that URL. It receives fixes and new features and never a breaking change, so a snippet pasted into a CMS today keeps working.

Snippet attributes

AttributeDefaultWhat it does
data-embed-url-Required. Your Experience Cloud page. Its origin is what every message between the page and the map is checked against.
data-map-The Map Unique Name to load. Leave it off for an empty map the page fills itself through loadData.
data-viewfullfull opens the frame at 640px, compact at 480px. The map measures itself and folds its legend and side rail down accordingly, so a compact frame really does produce a compact map.
data-heightfrom the viewHeight in pixels. Overrides data-view, and is the right answer whenever the page has an opinion.
data-max-widthnoneA width cap in pixels.
data-titleMapThe frame's accessible name, read by screen readers.
data-context-JSON. Ambient context the map starts holding, the same values setContext sets later.
data-flstyle-Replaces the style contract wholesale, or off to send none.
data-test-Hides the map from everyone but you. See below.

Test mode

Adding data-test hides the map from everyone. It renders only for someone who arrives with ?testflmap=1 in the URL, and it stays visible for them as they move around the site for the rest of that browser tab. ?testflmap=0 turns it back off without closing the tab.

Paste the real snippet onto the real page, check it, then remove the attribute to launch.


For Developers

This section covers programmatic usage of the Mosaic components when embedding them as child Lightning Web Components.

Component Markup

Map component:

<c-mosaic_map
map-unique-name="customer-overview"
style-config='{"height": "80vh", "minHeight": "400px"}'>
</c-mosaic_map>

map-unique-name is the only required attribute. It must match a Map_Unique_Name__c value on your Mosaic Setting records.

Map Preview (picker) component:

<c-mosaic_mapPreviewer></c-mosaic_mapPreviewer>

Takes no properties. Fetches every configured map at load time, renders a dropdown, and mounts the map for the user's selection.

Property Reference

c-mosaic_map

PropertyTypeDefaultDescription
map-unique-nameString-Required. Identifies which configured map to load.
style-configString (JSON)-CSS sizing overrides. Supported keys: height, minHeight, maxHeight.

Both properties are also surfaced as design fields in App Builder.

c-mosaic_mapPreviewer

No configurable properties. Available on App Pages only.

Style Config Reference

KeyDescriptionExample values
heightOuter container height"80vh", "600px", "100%"
minHeightMinimum height"400px"
maxHeightMaximum height"900px"

Embedding Examples

Record page (fixed height):

<c-mosaic_map
map-unique-name="account-territory"
style-config='{"height": "600px"}'>
</c-mosaic_map>

Full-height sidebar embed:

<c-mosaic_map
map-unique-name="customer-overview"
style-config='{"height": "100%", "minHeight": "500px"}'>
</c-mosaic_map>

Experience Cloud pages: Both components support lightningCommunity__Page. Confirm the community user has read access to Mosaic_Layer__c, Mosaic_Byte__c, and Mosaic_Setting__c.

Driving the map from a parent component

A parent LWC can drive a mounted map and listen to what it does. The map exposes four methods and one event.

MethodDoes
executeAction(name, params, meta)Runs one action. Resolves { success, data } or { success, error }, and never rejects, so branch on the result rather than catching.
getContext()Returns the context document: the map's identity, its layers by name, the current view, and the actions available.
getAvailableActions()The action list on its own.
setBusy(flag)Shows or clears the map's busy indicator while the host is doing something.
const res = await this.template.querySelector('c-mosaic_map')
.executeAction('flyTo', { lat: 29.76, lng: -95.37, zoom: 12 });
if (!res.success) console.error(res.error);

Calls run one at a time, in order, and a call made before the map has finished loading waits rather than failing. So a host can issue load, then color, then fit on page load and rely on them arriving in that sequence.

Actions cover the view (flyTo, setView, getView, changeTheme), highlighting (highlight, clearHighlights, highlightAndFlyTo), layers (listLayers, toggleRegion, togglePoint, toggleAllPoints, removePointLayer, reorderRegion, setRegionOpacity), filters (addFilter, removeFilter, clearFilters), and building a map from nothing (loadData, colorBy, fitTo, saveLayer).

loadData takes GeoJSON or CSV as text and runs it through the same path a dropped file takes, so a host can hand the map data it assembled itself and then color and fit it.

Listening to the map

The map dispatches a composed mosaicevent for everything it does:

typeWhen
mosaic.readyStartup finished. Carries the context document, with the layers a caller can name.
mosaic.contextThe layer set changed. Carries the same document.
mosaic.pointclickA point was clicked.
mosaic.viewchangedThe map was panned or zoomed.
mosaic.actionresultAn action finished.

Every payload carries mapUniqueName, a monotonic seq, and an origin of host when your own action caused it or user when a person did. Branching on origin is what keeps a listener from writing a feedback loop.

handleMosaicEvent(e) {
const { type, origin, ...rest } = e.detail;
if (type === 'mosaic.ready') this.layers = rest.layers;
}

Wait for mosaic.ready before naming a layer. It fires once the data has landed, so the layers it lists are the ones an action can actually address. A map with nothing configured answers with a null map and no layers, which is the signal to build a layer rather than look for one.

Driving an embedded map

When the map is framed on a website rather than mounted as a child component, the same surface is reachable from the host page. The loader exposes window.FlourishMap for the first map on the page, and window.FlourishMaps for all of them in the order they appear.

MethodDoes
execute(name, params)Runs one action. Resolves { success, data } or { success, error }, and never rejects.
getContext()Resolves with the context document: the map's identity, its layers by name, the current view, and the action names.
context()The last document the map announced, synchronously, without asking again.
setContext(object)Replaces the ambient values the map holds. It replaces the whole object rather than merging, so send every key you want kept, every time.
setBusy(busy, label)Raises or clears your own busy state while the page is working. Separate from the map's own loading indicator.
setView(view) / setHeight(px)Geometry. setView moves the frame and the map re-measures and folds accordingly, unless the page pinned data-height.
fullscreen(on)True fullscreen. See below.
reload()Discards the frame and starts over.
debug()The frame address and what this embed is holding.

An action can be awaited, which is the one thing an embedded map can do that an embedded chatbot cannot:

const res = await FlourishMap.execute('flyTo', { lat: 29.76, lng: -95.37, zoom: 12 });
if (!res.success) console.error(res.error);

The action names are the same ones a parent component calls, listed under Driving the map from a parent component.

Calls made before the map is ready are held, not lost. The map's cold start is its mapping library, then its settings, then layer definitions, then bytes, so a page firing on DOMContentLoaded is exactly the page that would otherwise lose its first call. The queue holds 25 and drops the oldest first, and a dropped call still settles rather than leaving you awaiting a promise that never resolves.

Everything the map announces is re-dispatched onto your page as a flourish: event, so you never have to write a message handler:

window.addEventListener('flourish:pointclick', function (e) {
if (e.detail.product !== 'mosaic') return; // another Flourish embed on the page
e.detail.data; // the point's metadata
});

The name is flourish: followed by the event, so flourish:ready, flourish:context, flourish:pointclick, flourish:viewchanged, and flourish:actionresult. Each detail carries product and an instance identifying which embed spoke, alongside the event's own fields. Events the loader does not recognize are relayed too, so a new one from a future release reaches your page without the loader needing an update first.

fullscreen() has to be called from a click handler, because browsers only grant fullscreen on a real user gesture. Use it rather than the map's own fullscreen control, which inside a frame can only fill the frame.

button.addEventListener('click', function () { FlourishMap.fullscreen(true); });