<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Hello Nakama</title>
    <description>The latest articles on DEV Community by Hello Nakama (@hello_nakama_f89fb103e925).</description>
    <link>https://dev.to/hello_nakama_f89fb103e925</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4144793%2Fcc56c40d-ebe3-4575-96d8-4489f7eef1dd.png</url>
      <title>DEV Community: Hello Nakama</title>
      <link>https://dev.to/hello_nakama_f89fb103e925</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/hello_nakama_f89fb103e925"/>
    <language>en</language>
    <item>
      <title>LocalBusiness Schema for Multi-Location Sites: A Practical JSON-LD Pattern</title>
      <dc:creator>Hello Nakama</dc:creator>
      <pubDate>Sat, 26 Sep 2026 20:38:55 +0000</pubDate>
      <link>https://dev.to/hello_nakama_f89fb103e925/localbusiness-schema-for-multi-location-sites-a-practical-json-ld-pattern-2a1h</link>
      <guid>https://dev.to/hello_nakama_f89fb103e925/localbusiness-schema-for-multi-location-sites-a-practical-json-ld-pattern-2a1h</guid>
      <description>&lt;p&gt;For a multi-location site, put one &lt;code&gt;Organization&lt;/code&gt; node on the brand level, and one &lt;code&gt;LocalBusiness&lt;/code&gt; node (or a more specific subtype) on each location page. Give every node a stable &lt;code&gt;@id&lt;/code&gt;, link each location to the brand with &lt;code&gt;parentOrganization&lt;/code&gt;, and make sure the address, phone, and hours in the markup match the visible page and the Google Business Profile exactly. That is most of it. The rest is keeping it true.&lt;/p&gt;

&lt;p&gt;Here is a pattern that scales from five locations to five hundred.&lt;/p&gt;

&lt;h2&gt;
  
  
  When should you use LocalBusiness?
&lt;/h2&gt;

&lt;p&gt;Use it on pages that represent a real, physical place customers can visit or that serves a defined area. A store page, a clinic page, a branch page.&lt;/p&gt;

&lt;p&gt;Do not use it just because your site talks about local topics. A blog about local marketing is not a local business. Google's &lt;a href="https://developers.google.com/search/docs/appearance/structured-data/local-business" rel="noopener noreferrer"&gt;local business structured data docs&lt;/a&gt; describe the intended use.&lt;/p&gt;

&lt;h2&gt;
  
  
  The brand node
&lt;/h2&gt;

&lt;p&gt;Put this on the homepage, or in a shared layout, with the same &lt;code&gt;@id&lt;/code&gt; everywhere:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"@context"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://schema.org"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"@type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Organization"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"@id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://example.com/#organization"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Example Hardware"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://example.com/"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"logo"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://example.com/logo.png"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"sameAs"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"https://www.linkedin.com/company/example-hardware"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Only include &lt;code&gt;sameAs&lt;/code&gt; profiles that are real and owned by the brand.&lt;/p&gt;

&lt;h2&gt;
  
  
  The location node
&lt;/h2&gt;

&lt;p&gt;On each location page, one node per location:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"@context"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://schema.org"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"@type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"HardwareStore"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"@id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://example.com/locations/austin-north/#location"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Example Hardware Austin North"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://example.com/locations/austin-north/"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"telephone"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"+1-512-555-0100"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"address"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"@type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"PostalAddress"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"streetAddress"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"123 Example Rd"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"addressLocality"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Austin"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"addressRegion"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"TX"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"postalCode"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"78701"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"addressCountry"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"US"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"geo"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"@type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"GeoCoordinates"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"latitude"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;30.27&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"longitude"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;-97.74&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"openingHoursSpecification"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"@type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"OpeningHoursSpecification"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"dayOfWeek"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Monday"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s2"&gt;"Tuesday"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s2"&gt;"Wednesday"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s2"&gt;"Thursday"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s2"&gt;"Friday"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"opens"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"08:00"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"closes"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"19:00"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"@type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"OpeningHoursSpecification"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"dayOfWeek"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Saturday"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"opens"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"09:00"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"closes"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"17:00"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"parentOrganization"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"@id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://example.com/#organization"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The address and phone above are placeholder examples. Use your real data.&lt;/p&gt;

&lt;p&gt;A few notes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Use the most specific subtype&lt;/strong&gt; that fits, such as &lt;code&gt;HardwareStore&lt;/code&gt;, &lt;code&gt;Dentist&lt;/code&gt;, or &lt;code&gt;Restaurant&lt;/code&gt;. Fall back to &lt;code&gt;LocalBusiness&lt;/code&gt; if nothing fits.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The &lt;code&gt;@id&lt;/code&gt; is an identifier, not a link.&lt;/strong&gt; Keep it stable. Changing it later breaks the connection between nodes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;parentOrganization&lt;/code&gt; points to the brand &lt;code&gt;@id&lt;/code&gt;,&lt;/strong&gt; so crawlers see one brand with many locations.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Generate it from the same data as the page
&lt;/h2&gt;

&lt;p&gt;The biggest schema bug on multi-location sites is drift. The page says one set of hours, the markup says another, and the Google profile says a third.&lt;/p&gt;

&lt;p&gt;Fix it structurally. Render the visible hours and the JSON-LD from the same location record:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;locationJsonLd&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;loc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;site&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@context&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://schema.org&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;loc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;schemaType&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;LocalBusiness&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;site&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;locations/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;loc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;slug&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/#location`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;loc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;site&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;locations/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;loc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;slug&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;telephone&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;loc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;phoneE164&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;address&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;PostalAddress&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;streetAddress&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;loc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;street&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;addressLocality&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;loc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;city&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;addressRegion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;loc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;region&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;postalCode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;loc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;postalCode&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;addressCountry&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;loc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;country&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;openingHoursSpecification&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;loc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;hours&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;h&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;OpeningHoursSpecification&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;dayOfWeek&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;h&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;days&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;opens&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;h&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;opens&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;closes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;h&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;closes&lt;/span&gt;
    &lt;span class="p"&gt;})),&lt;/span&gt;
    &lt;span class="na"&gt;parentOrganization&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;site&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;#organization`&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the page template and the schema read from one object, they cannot disagree.&lt;/p&gt;

&lt;h2&gt;
  
  
  Handle special hours
&lt;/h2&gt;

&lt;p&gt;Holiday hours can go in &lt;code&gt;openingHoursSpecification&lt;/code&gt; with &lt;code&gt;validFrom&lt;/code&gt; and &lt;code&gt;validThrough&lt;/code&gt;. Remove them after the date passes. Stale holiday entries are a common source of wrong answers in search and AI tools.&lt;/p&gt;

&lt;h2&gt;
  
  
  Common mistakes
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Mistake&lt;/th&gt;
&lt;th&gt;Why it hurts&lt;/th&gt;
&lt;th&gt;Fix&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;One LocalBusiness on the homepage for all locations&lt;/td&gt;
&lt;td&gt;Merges many places into one&lt;/td&gt;
&lt;td&gt;One node per location page&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Markup hours differ from page&lt;/td&gt;
&lt;td&gt;Conflicting signals&lt;/td&gt;
&lt;td&gt;Render both from one record&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Changing &lt;code&gt;@id&lt;/code&gt; values&lt;/td&gt;
&lt;td&gt;Breaks entity links&lt;/td&gt;
&lt;td&gt;Treat &lt;code&gt;@id&lt;/code&gt; as permanent&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Adding reviews you do not show&lt;/td&gt;
&lt;td&gt;Against guidelines&lt;/td&gt;
&lt;td&gt;Only mark up visible, real content&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;LocalBusiness on non-location pages&lt;/td&gt;
&lt;td&gt;Misleading&lt;/td&gt;
&lt;td&gt;Limit to real place pages&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Keeping it true at scale
&lt;/h2&gt;

&lt;p&gt;Markup is only as good as the data behind it. If your hours live in five places, the schema will eventually be wrong somewhere. Most multi-location teams either keep a central location database that feeds the site, or use a listing platform that also powers location pages.&lt;/p&gt;

&lt;p&gt;Options vary. Yext offers pages driven by its knowledge graph, with enterprise pricing and setup. &lt;a href="https://www.synup.com" rel="noopener noreferrer"&gt;Synup&lt;/a&gt; has store locator and local pages tied to its listings data, though teams with a custom CMS may prefer to keep rendering in their own stack and use its API instead. Uberall offers locator pages for international brands with sales-led onboarding. Or you build it yourself, which gives full control and full maintenance cost.&lt;/p&gt;

&lt;h2&gt;
  
  
  Validate before shipping
&lt;/h2&gt;

&lt;p&gt;Run pages through Google's Rich Results Test and the Schema Markup Validator. Then spot check that the rendered HTML, not just your source, contains the JSON-LD, especially on client-rendered frameworks.&lt;/p&gt;

&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Should every location page have its own LocalBusiness node?&lt;/strong&gt;&lt;br&gt;
Yes, if each page represents a distinct physical location.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Can I list all locations in one JSON-LD block on a store locator page?&lt;/strong&gt;&lt;br&gt;
You can reference them, but the full details belong on each location's own page.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Do I need geo coordinates?&lt;/strong&gt;&lt;br&gt;
They are optional but helpful. Use accurate values from your source data.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Does schema affect Google Business Profile?&lt;/strong&gt;&lt;br&gt;
No. They are separate. Keep them consistent by hand or through a shared data source.&lt;/p&gt;

</description>
      <category>seo</category>
      <category>javascript</category>
      <category>webdev</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Syncing Location Data to Google Business Profile Without Breaking It</title>
      <dc:creator>Hello Nakama</dc:creator>
      <pubDate>Sat, 26 Sep 2026 20:30:55 +0000</pubDate>
      <link>https://dev.to/hello_nakama_f89fb103e925/syncing-location-data-to-google-business-profile-without-breaking-it-3lap</link>
      <guid>https://dev.to/hello_nakama_f89fb103e925/syncing-location-data-to-google-business-profile-without-breaking-it-3lap</guid>
      <description>&lt;p&gt;A reliable Google Business Profile sync has four parts: one internal source of truth, field-level updates with an update mask, a read-back step that compares what Google actually shows, and a queue for edits Google rejected or changed. Most broken syncs skip the read-back. They assume a successful API response means the listing is live and correct. It does not.&lt;/p&gt;

&lt;p&gt;These are practical notes for engineers building or maintaining a location data pipeline, whether for one brand or many.&lt;/p&gt;

&lt;h2&gt;
  
  
  What are you actually syncing?
&lt;/h2&gt;

&lt;p&gt;A location record usually includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Business name&lt;/li&gt;
&lt;li&gt;Address and service area&lt;/li&gt;
&lt;li&gt;Primary phone&lt;/li&gt;
&lt;li&gt;Regular hours and special hours&lt;/li&gt;
&lt;li&gt;Primary and additional categories&lt;/li&gt;
&lt;li&gt;Website URL&lt;/li&gt;
&lt;li&gt;Attributes (accessibility, payment types, and so on)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Keep these in your own datastore with a stable internal ID per location, and map that ID to the Google location resource name. Never treat Google as the source of truth. It is a destination, and one that can change your data.&lt;/p&gt;

&lt;h2&gt;
  
  
  Which APIs are involved?
&lt;/h2&gt;

&lt;p&gt;Google split the old My Business API into several APIs. For location data, the main one is the &lt;strong&gt;Business Information API&lt;/strong&gt;, which reads and updates location fields. Account and access work sits in the &lt;strong&gt;Account Management API&lt;/strong&gt;. Access to these APIs is not automatic. You request it through Google, and approval takes time, so plan for that before you build.&lt;/p&gt;

&lt;p&gt;Check the current &lt;a href="https://developers.google.com/my-business" rel="noopener noreferrer"&gt;Business Profile APIs documentation&lt;/a&gt; for scopes, quotas, and endpoints, because details change.&lt;/p&gt;

&lt;h2&gt;
  
  
  Update one field at a time with a field mask
&lt;/h2&gt;

&lt;p&gt;Send only what changed. The update call takes an &lt;code&gt;updateMask&lt;/code&gt;, and anything outside the mask is left alone.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;PATCH https://mybusinessbusinessinformation.googleapis.com/v1/locations/{locationId}?updateMask=regularHours
Content-Type: application/json

{
  "regularHours": {
    "periods": [
      { "openDay": "MONDAY", "openTime": { "hours": 9 }, "closeDay": "MONDAY", "closeTime": { "hours": 18 } }
    ]
  }
}
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Why this matters:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A full-record overwrite can wipe fields another team or the owner edited directly.&lt;/li&gt;
&lt;li&gt;Narrow masks make failures easier to diagnose.&lt;/li&gt;
&lt;li&gt;Smaller payloads are easier to audit.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Build your diff logic to emit a mask per changed field, not per record.&lt;/p&gt;

&lt;h2&gt;
  
  
  Make every write idempotent
&lt;/h2&gt;

&lt;p&gt;Your sync will retry. Networks fail, quotas bite, jobs restart. Design so that sending the same update twice has the same result as sending it once.&lt;/p&gt;

&lt;p&gt;A simple pattern:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;sync_location&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;loc&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;desired&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;normalize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;loc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;source_record&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;current&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;normalize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;fetch_google_location&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;loc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;google_name&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="n"&gt;changed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;diff_fields&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;desired&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;current&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;changed&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;noop&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="n"&gt;mask&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;,&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;changed&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;patch_location&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;loc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;google_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;desired&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;update_mask&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;mask&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;enqueue_readback&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;loc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;changed&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;delay_minutes&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;patched&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Normalization is the unglamorous core. Phone formats, time zones, trailing slashes on URLs, and whitespace in names all create false diffs if you do not normalize both sides the same way.&lt;/p&gt;

&lt;h2&gt;
  
  
  Read back what Google actually shows
&lt;/h2&gt;

&lt;p&gt;Google can accept an update, then modify or reject it after review. It can also apply edits from users or its own data sources. The Business Information API exposes a way to fetch the Google-updated version of a location, which shows where Google's view differs from what you sent.&lt;/p&gt;

&lt;p&gt;Your read-back job should:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Fetch the location after a delay.&lt;/li&gt;
&lt;li&gt;Compare each changed field to the desired value.&lt;/li&gt;
&lt;li&gt;Mark the change as &lt;code&gt;live&lt;/code&gt;, &lt;code&gt;modified&lt;/code&gt;, or &lt;code&gt;rejected&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Alert a human for anything not &lt;code&gt;live&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;State&lt;/th&gt;
&lt;th&gt;Meaning&lt;/th&gt;
&lt;th&gt;Action&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;live&lt;/td&gt;
&lt;td&gt;Google shows your value&lt;/td&gt;
&lt;td&gt;Close the change&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;modified&lt;/td&gt;
&lt;td&gt;Google shows a different value&lt;/td&gt;
&lt;td&gt;Review, possibly contest&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;rejected&lt;/td&gt;
&lt;td&gt;Update did not apply&lt;/td&gt;
&lt;td&gt;Check guidelines, fix data, resubmit&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;pending&lt;/td&gt;
&lt;td&gt;Not resolved yet&lt;/td&gt;
&lt;td&gt;Recheck later&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Without this table in your system, you are guessing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Detect drift on a schedule
&lt;/h2&gt;

&lt;p&gt;Even when nothing changes on your side, listings drift. A user suggests new hours. Google infers a category. Run a scheduled job that fetches every location, diffs against your source of truth, and reports differences. Decide per field whether to auto-revert or flag for review. Auto-reverting hours is usually safe. Auto-reverting a name change Google made after a guideline review is not.&lt;/p&gt;

&lt;h2&gt;
  
  
  Respect quotas and back off
&lt;/h2&gt;

&lt;p&gt;The APIs have quotas. Batch work by account, spread writes over time, and use exponential backoff on rate-limit errors. Log every request and response with the internal location ID. When someone asks why a listing changed, the log is your answer.&lt;/p&gt;

&lt;h2&gt;
  
  
  Build or buy?
&lt;/h2&gt;

&lt;p&gt;If you manage a few locations, a small script plus a spreadsheet may be enough. If you manage many, or need Apple Business Connect, Bing Places, and directories too, building every integration yourself gets expensive to maintain.&lt;/p&gt;

&lt;p&gt;Listing platforms with APIs can sit in the middle. Yext has a deep API and data model, but it is enterprise-weight. &lt;a href="https://www.synup.com" rel="noopener noreferrer"&gt;Synup&lt;/a&gt; offers listing APIs and MCP support for LLM tooling, though you still need to design your own source of truth and review flow around it. Uberall provides APIs aimed at larger international brands, with sales-led onboarding. BrightLocal has an API focused more on audits and citation data than on direct profile management. Whichever route you take, keep the read-back and drift checks. A vendor can distribute data, but your system should still verify it.&lt;/p&gt;

&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Can I use the API without approval?&lt;/strong&gt;&lt;br&gt;
No. You need to request access to the Business Profile APIs first.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Should I overwrite user-suggested edits automatically?&lt;/strong&gt;&lt;br&gt;
Only for fields where you are certain your data is correct, such as hours. Review the rest.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How often should drift checks run?&lt;/strong&gt;&lt;br&gt;
Daily is common for multi-location brands. Weekly can work for small, stable portfolios.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Does the API update Apple Maps or Bing?&lt;/strong&gt;&lt;br&gt;
No. Those platforms have their own tools and processes.&lt;/p&gt;

</description>
      <category>api</category>
      <category>architecture</category>
      <category>automation</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
