Multi-branch

Branch locations and hours: one source of truth for every store

Store details rot faster than anything else on a website. Hours change at Easter, a phone number moves, a branch relocates two streets over, and the website is the last thing anyone updates.

GoGee keeps branch details as structured data rather than typed page copy, sourced where possible from the branch's own Google listing, so one correction fixes every place that store appears.

GoGee feature series · 13 of 33

How it's actually built

Location data
Street address, city, province, postal code, latitude and longitude
Google linkage
Google Place ID stored per branch
Hours
Opening-hours JSON normalised from the Google Places response
Contact
Per-branch phone and email
Nearest branch
Haversine distance from the visitor's resolved location
Visibility
Public read of active branches; admin-only writes
Store data pipeline
  1. 01Input

    Google Place ID

    Stored per branch

  2. 02Database

    Places lookup

    Details and opening hours fetched

  3. 03Deterministic

    Normalisation

    Hours mapped into one weekly structure

  4. 04Database

    Branch record

    Address, coordinates, contact, hours

  5. 05Output

    Storefront use

    Nearest branch, hours and directions links

Guardrails and fallbacks

  • Public read of active branches only
  • Admin-only writes

Branch locator with maps, data flow, generated from the shared GoGee feature diagram template.

Structured, not typed into a page

Each branch is a database row carrying its address parts, coordinates, contact details, active flag and an opening-hours structure. Because it is data, the same branch can be rendered on a store page, in a checkout collection picker, in stock messaging and in a feed without anyone re-typing it.

Coordinates matter more than they sound: they are what makes "nearest branch" a calculation rather than a guess, and they are what makes a directions link land on the right pin.

Hours come from the branch's Google listing

Where a branch has a Google Place ID, its details and opening hours are pulled from the Google Places API and normalised into a consistent weekly structure before being stored. That means the hours on the website match the hours a customer sees in Google Maps.

Normalising on the way in is deliberate. Google's payload shape is not something you want spread through your front end, and a single normaliser keeps display, sorting and holiday handling in one place.

  • Place ID per branch links the record to its real listing
  • Opening hours normalised into one weekly structure on import
  • Ratings and listing media can be captured alongside
  • Directions links built from stored coordinates

Nearest branch, and who can change it

The visitor's location is resolved and branches are ranked by straight-line distance, so the store shown first is the one they can actually get to. Only active branches are publicly readable, and writes are restricted to administrators through row-level security.

That split is the point: the public gets fast, correct reads, and nobody edits store data from the browser without the right role.

Being precise about the map

The location data, hours, coordinates and directions links are all real and in production. A full interactive multi-pin map component with filters is a front-end addition on top of this data rather than something already shipped, worth stating plainly, because the data layer is the hard part and it exists.

If a client wants a pin map, it is built from these same rows, which is why it stays consistent with checkout, stock and feeds.

Questions we get asked

Where do the opening hours come from?

From the branch's Google listing via the Places API, normalised into a consistent weekly structure and stored on the branch record.

How is the nearest store chosen?

By straight-line distance between the visitor's resolved location and each active branch's stored coordinates.

Is there an interactive map with pins?

The data behind one, coordinates, hours, contact and directions, is in production; the pin-map interface is built per project on top of it.