Builds site selection and cannibalization analysis workflows in CARTO. Triggers when the user mentions site selection, cannibalization, cannibalizing, new store location, where to open, optimal location, facility placement, network impact, overlapping catchments, twin areas, similar locations, look-alike areas, find locations like my best, store overlap, revenue impact of new store, commercial hotspots, demand hotspots, location scoring, location ranking, expand network, new branch, franchise placement, EV charging siting, or wants to evaluate candidate sites, quantify overlap between trade areas, or find areas that resemble top-performing locations.
Builds CARTO Workflows that identify optimal locations for new facilities (stores, stations, offices) by combining spatial criteria, and that quantify cannibalization risk from overlapping catchment areas. Also covers twin-area and similar-location discovery.
Prerequisites: Load build-carto-workflow for the full workflow development process, JSON structure, and validation commands. Load trade-area-analysis if the workflow involves isochrones, buffers, or catchment enrichment — that skill covers the catchment pipeline in detail.
| User intent | Pattern |
|---|---|
| "Where should I open a new store?" | Site Selection (scoring + ranking) |
| "Will a new store hurt existing ones?" | Cannibalization Analysis |
| "Find locations similar to my best performers" | Twin Areas / Similar Locations |
Existing locations + Target area -> Spatial indexing -> Enrich with demographics/POIs -> Score/Rank -> Filter top candidates -> Save
Load two datasets with native.gettablebyname:
Success: Both tables loaded with geometry columns and unique identifiers.
Polyfill the target area into H3 or Quadbin cells using native.h3polyfill or native.quadbinpolyfill. Each cell is a candidate micro-location.
Success: A contiguous grid of cells covering the study area.
Attach demand signals to each cell — population, income, foot traffic, POI density — using native.h3enrich, native.joinv2, or the Data Observatory.
Success: Each grid cell has numeric columns representing demand/suitability factors.
Use native.h3distance to compute hop distance from each candidate cell to the nearest existing location. Filter out cells that are too close (cannibalization risk) or too far (logistics cost).
native.h3distance returns hop count, not physical distance. Convert using the approximate edge length for the resolution (e.g. H3 res 8 ~ 460m edge, so 3 hops ~ 1.4 km).Success: Candidate cells are within a sensible distance band from existing locations.
Use the scoring pattern from trade-area-analysis:
native.normalizenative.selectexpression with user-defined weightsnative.orderby (descending) + native.limit (top N)Success: A ranked shortlist of candidate cells with composite scores and contributing variables.
Use native.saveastable. The H3/Quadbin column is directly visualizable in CARTO Builder.
Success: Validated workflow ready to upload.
Existing + Proposed locations -> Trade areas (isoline/buffer) -> Polyfill to grid -> Intersect/Join -> Measure overlap -> Save
Load existing locations and proposed locations (or a single table with a flag column distinguishing them).
Success: Both sets loaded with geometry and unique identifiers.
Create catchment areas around both existing and proposed locations using native.isolines (realistic) or native.buffer (simple). Use the same parameters for both sets to ensure comparability.
Success: Every location has a catchment polygon with consistent parameters.
Convert all catchment polygons to H3 or Quadbin cells with native.h3polyfill. Preserve the location identifier and an is_proposed flag.
Success: One row per cell per location, with location ID and type flag.
Use native.joinv2 (inner join on the spatial index column) between existing-location cells and proposed-location cells. The result contains cells shared by at least one existing and one proposed location.
Success: Output contains only cells that fall in both an existing and a proposed catchment.
Use native.groupby to aggregate overlap:
Use native.selectexpression to compute the overlap ratio.
Success: Each existing location has an overlap metric showing how much of its catchment is shared with proposed locations.
Use native.saveastable.
Success: Validated workflow with per-location cannibalization metrics.
Top-performing locations -> Trade areas -> Enrich -> Build similarity model -> Score all candidate areas -> Rank -> Save
Load the full location dataset. Filter to top performers (e.g. top quartile by revenue) using native.wheresimplified or native.orderby + native.limit.
Success: A subset of high-performing locations isolated as the reference set.
Create isochrone or buffer trade areas around reference locations. Polyfill to H3/Quadbin. Enrich with demographics, POIs, and any relevant variables.
Success: Each reference location has a rich demographic profile.
Use native.buildtwinareasmodel (BUILD_TWIN_AREAS_MODEL) to create a PCA-based similarity model from the enriched reference locations.
Success: A model artifact that encodes the demographic profile of top performers.
Use native.findsimilarlocations (FIND_SIMILAR_LOCATIONS) to score all candidate areas against the twin-areas model.
Success: Every candidate area has a similarity score relative to the reference set.
Rank by similarity score descending. Save top candidates.
Success: A ranked list of areas most similar to top-performing locations.
For demand-driven site selection (e.g. "where is unmet demand highest?"), use native.commercialhotspots:
native.commercialhotspots with variablecolumns and weightsp_value < 0.05)native.h3distance from existing locations to focus on underserved areasNote: variablecolumns uses Python-style list syntax (['col1', 'col2']), and weights is comma-separated — see the trade-area-analysis gotchas for details.
native.commercialhotspots requires the Retail module of the Analytics Toolbox. Validate with --connection to confirm availability.native.h3distance returns hop count, not physical distance. Multiply by the approximate cell edge length for the resolution to get a rough metric distance (e.g. res 8 ~ 460m, res 9 ~ 174m per hop).| Tutorial | Provider | URL |
|---|---|---|
| Pizza Hut Honolulu — site selection with commercial hotspots | BigQuery | Link |
| Pizza Hut Honolulu — site selection with commercial hotspots | Snowflake | Link |
| Store cannibalization — quantifying new store impact | BigQuery | Link |
| Starbucks cannibalization — H3 grid overlap analysis | BigQuery | Link |
| Store cannibalization — Quadkey grid overlap | Snowflake | Link |
| Find twin areas of top-performing stores | BigQuery | Link |
| Find similar locations based on trade areas |
| Variant | How |
|---|---|
| Retail expansion | Isochrones -> enrich with demographics + competitor density -> composite score -> top N |
| Franchise territory planning | Cannibalization pattern to ensure non-overlapping catchments before awarding territories |
| EV charging / public services | Grid-based demand (population, traffic) + distance-from-existing filter -> rank underserved cells |
| Billboard / OOH placement | Buffers -> audience enrichment -> normalize + weight -> top N (see trade-area-analysis) |
| Bank branch optimization | Twin areas from top branches -> find similar underserved areas -> propose new branches |
| Competitor proximity analysis | H3 distance to competitor locations -> filter cells far from competitors but near demand |
| BigQuery |
| Link |
| EV charging station site selection | Workflows | Link |