Technical Local SEO

How to Generate Accurate UULE for City-Level Checks

A practical, repeatable method for producing high-quality UULE tokens for city-level local SERP checks — covering canonicalization, geocoding, and validation.

A UULE token is only as accurate as the canonical location string it encodes. For city-level local SERP checks — the bread and butter of multi-market local SEO audits — the difference between a sloppy UULE and a clean one shows up directly in the Map Pack you see, the organic listings that load, and the conclusions you draw about competitor positioning. The encoding step itself is trivial. The canonicalization that comes before it is where most teams either earn or squander accuracy.

You can run these checks yourself with Local SERP Checker, a free tool that opens the real localized Google results for any city, ZIP, or neighborhood.

This article walks through a repeatable process for generating accurate, audit-grade UULE tokens at city granularity. It assumes you've read the basics of how UULE works (prefix, length key character, base64-encoded canonical name) and focuses on the operational details that separate reliable tooling from approximations. The framing draws from how we generate city-level UULE tokens in our own local SERP Checker tool, across both U.S. and international markets.

Define "City-Level" Before You Encode

City granularity sounds obvious until you try to define it precisely. Different parts of the world use different administrative geographies, and the canonical names Google recognizes don't always match local convention.

A few cases to internalize:

  • United States. City + state + country. "Austin, Texas, United States" is the right form. Counties and metropolitan statistical areas (MSAs) are rarely what you want for city-level checks.
  • United Kingdom. City + region (often a county or constituent country) + country. "Manchester, England, United Kingdom" works. "Manchester, Greater Manchester, United Kingdom" can also work but is wordier.
  • Canada. City + province + country. "Toronto, Ontario, Canada" is the right form.
  • Germany. City + state (Bundesland) + country. "Munich, Bavaria, Germany" or "München, Bayern, Deutschland" — both can work, but consistency matters.
  • Brazil and other federations. City + state + country. "São Paulo, São Paulo, Brazil" works (yes, the city and state share a name).
  • Single-tier administrative countries. Some smaller countries don't have meaningful intermediate regions. "Luxembourg, Luxembourg" is the practical form.

Decide the convention you'll use for each country before encoding. Mixing forms across a portfolio — sometimes including state, sometimes omitting it — produces results that are hard to compare.

The Canonical Name Format Google Prefers

Across years of testing, a few patterns produce the most consistent localization quality:

  • Use ASCII when possible. Google handles UTF-8 fine, but ASCII reduces edge cases. "Sao Paulo, Sao Paulo, Brazil" tends to localize the same as "São Paulo, São Paulo, Brazil." For Latin-alphabet languages this barely matters; for Cyrillic, Arabic, or CJK scripts, use the native script and let UTF-8 + base64 handle it.
  • Comma-separated components. Use ", " between components ("Austin, Texas, United States"). Don't use slashes or pipes.
  • Title case. "Austin, Texas, United States" beats "austin, texas, united states." Google's edge isn't case-sensitive, but title case is the form most cities use canonically.
  • Spell out the country. "United States" beats "USA" or "US." "United Kingdom" beats "UK." The full name matches Google's place graph entries more cleanly.
  • Resolve abbreviations. "St. Louis" or "Saint Louis" — pick one, use it consistently. The same goes for "Mount" vs "Mt.", "Saint" vs "St."

Set this convention as a team standard. The point isn't that there's a single objectively correct form — it's that consistency across audits is what makes data comparable over time.

The Geocoding Step: Don't Skip It

The single most reliable way to produce a clean canonical name is to run user input through a geocoder before encoding. A geocoder takes a free-form string ("downtown Austin") and returns a structured address with components — locality, region, country, sometimes postcode and county. The tool then assembles those components into the canonical form you want.

Nominatim is the standard OpenStreetMap-backed geocoder used by many open-source SEO tools. It's free, well-documented, and accepts a countrycodes parameter to disambiguate when the same place name exists in multiple countries. A typical Nominatim request for city-level work:

https://nominatim.openstreetmap.org/search
  ?q=austin&format=jsonv2&addressdetails=1&limit=1
  &countrycodes=us&accept-language=en

The response includes an address object with city, state, country, and other components. The tool then assembles "Austin, Texas, United States" from those fields and encodes it.

Commercial geocoders — Google Maps Geocoding API, Mapbox, HERE — produce similarly structured results with stricter rate limits and better accuracy on edge cases. For agency-grade work running thousands of UULE generations per month, a commercial geocoder may be worth the cost. For individual or small-team use, Nominatim with rate-limiting and proper attribution is sufficient.

Picking the Right City Field From Geocoder Output

Geocoders return multiple "city-ish" fields and they don't always agree. Nominatim, for example, returns some combination of city, town, village, hamlet, suburb, and municipality. Which one is "the city" for your purposes?

A pragmatic priority order:

  1. city if present — the most common and intended field.
  2. town as a fallback — used for smaller incorporated places.
  3. village or hamlet for very small places, but at this granularity you usually want to escalate to the parent locality.
  4. suburb is sometimes useful for neighborhood-level checks, but for true city-level work it's wrong — you want the parent city.
  5. municipality can substitute when city is absent.

For city-level UULE, pick the first available from the priority order and use that as the locality. For ambiguous cases (large metro areas where Nominatim returns a borough rather than the parent city), test both forms and keep the one that produces results that match expected localization.

Validating UULE Output

Once you've generated a UULE, validate it. The cheapest validation is to construct the full search URL and open it in incognito. The Map Pack should clearly show businesses in the encoded city; the "results from [location]" indicator (when Google shows it) should match. If the pack shows businesses from a different city or a parent metro, the localization is weak — usually because the canonical name was too vague or the geocoder returned a parent geography.

For programmatic validation in a tool pipeline, a few sanity checks help:

  • Length sanity. UULE tokens for typical city-level canonical names are between 40 and 80 characters. Significantly shorter or longer suggests an encoding bug.
  • Length key character verification. Decode the third-to-last segment (the key char) and confirm it corresponds to the byte length of the encoded string.
  • Round-trip test. Base64-decode the body of the UULE and confirm it matches the canonical name you intended to encode.

Add these as automated unit tests if you're building tooling. A few minutes of test setup saves hours of confused audits later.

Edge Cases That Trip Up City-Level UULE

Several edge cases come up often enough to be worth pre-empting:

  • Cities that span multiple administrative regions. A few large U.S. cities (Kansas City, Texarkana) cross state lines. Use the dominant state for the city-level UULE, or run separate audits for each side.
  • Cities with the same name in different states. Springfield, Portland, Columbus, Aurora, Greenwood — there are dozens. Always include state and country to disambiguate.
  • Recently renamed places. Names change occasionally (Yangon was Rangoon; cities in Ukraine have been renamed). Google's place graph usually updates, but small towns can lag. Try both old and new names and use whichever produces a localized SERP that matches your expectation.
  • Non-Latin scripts. Cities with names in Cyrillic, Arabic, Hindi, Chinese, Japanese, or Korean encode in UTF-8 perfectly; base64 handles arbitrary bytes. The question is whether to use the native-script name or the romanized form. Test both — for queries targeting native-language searchers, the native script + matching hl usually localizes best.
  • Compound or hyphenated city names. "Saint-Étienne, France" — keep the hyphen and the accent. Resist the urge to "normalize" them away.

A Reference Workflow for Generating Accurate City-Level UULE

Putting it all together, the operational workflow:

  1. Input. User or tool provides a free-form city name plus a country code.
  2. Geocode. Call Nominatim (or commercial geocoder) with the city name, country code (countrycodes parameter), and an accept-language matching the hl you'll use.
  3. Pick city field. Use the priority order (citytownmunicipality) to identify the locality.
  4. Compose canonical name. Assemble Locality, Region, Country in title case, spelling out the country name, using comma-space separators.
  5. Encode. Apply the canonical-name UULE format: prefix + length key character + base64(canonical name).
  6. Build URL. Construct https://www.google.com/search?q=<keyword>&hl=<lang>&gl=<country>&uule=<uule>&pws=0&num=20.
  7. Validate. Open the URL in incognito; confirm pack listings match the encoded city.
  8. Log. Record canonical name, UULE, gl, hl, timestamp, and the query so the audit is reproducible.

Run that workflow every time and your city-level UULEs will be consistent, comparable across audits, and reliable when the question gets asked "are we sure this is what Phoenix looks like?"

Common Mistakes to Avoid

  • Skipping the geocoder. Encoding raw user input produces UULEs of variable quality. Always normalize through a geocoder.
  • Mixing locale conventions. Sometimes including state, sometimes not. Pick a convention per country and stick to it.
  • Trusting the first geocoder hit blindly. Ambiguous names (Springfield) need the country filter; without it, the geocoder may return a different country than intended.
  • Not re-encoding on changes. When the country or language changes, re-encode. Stale UULEs are a leading cause of confused audits.
  • Forgetting to set accept-language on the geocoder call. Nominatim returns localized city names depending on the request language. Setting accept-language=en for U.S. cities keeps results stable; setting accept-language=de for German cities returns German names cleanly.

When You Need Sub-City Precision

City-level UULE is sufficient for many audits, but service-area businesses and large-metro brands often need finer granularity. For neighborhood-level work, the canonical form becomes "Neighborhood, City, Region, Country" — for example, "Park Slope, Brooklyn, New York, United States." For ZIP-code-level work, the form is typically "ZIP, City, Region, Country" — "10001, New York, New York, United States." The encoding pipeline is the same; only the input changes. Pair sub-city UULEs with multiple audits across the service area for the most informative read.

The Bottom Line

Accurate city-level UULE generation is a craft built from small disciplines: define your locale convention, geocode every input, pick the right city field, compose a clean canonical name, encode it correctly, validate the resulting SERP, and log the canonical name alongside the UULE for reproducibility. Get those steps right and city-level localization stops being a source of audit drift and becomes a reliable measurement axis. The encoding is trivial; the disciplined canonicalization is where the accuracy lives.

UULEgeocodinglocal SERPNominatim
HK

Hassnain Karim

Local SEO Expert

Local SEO expert focused on the U.S. market. Writes about local search, UULE geotargeting, Google Business Profile optimization, and location-based SERP analysis.

Ready to open localized Google results?

Enter keyword, country, and location. We build the URL and open the real Google SERP in a new tab.

Open the checker