Install
This is the repository archive. It installs, but the folder name will carry the branch suffix and updates will not flow.
Install straight from GitHub with WP-CLI:
wp plugin install https://github.com/ecds/open-geographies-wp/archive/refs/heads/main.zipOpen Geographies — WordPress Plugin
Fetches JSON from a remote API endpoint based on the current page's URL slug, then lets you drop individual fields into any template or page using shortcodes.
Installation
- Copy the
open-geographies/folder intowp-content/plugins/. - Activate Open Geographies in Plugins → Installed Plugins.
- Go to Settings → Open Geographies and enter your API base endpoint.
Updating via Git Updater
This plugin isn't on wordpress.org — it ships updates straight from this GitHub repo using Git Updater. The plugin header already declares what Git Updater needs:
GitHub Plugin URI: ecds/open-geographies-wp
Primary Branch: main
One-time setup (per WordPress site)
- Install and activate Git Updater (
git-updater.zipfrom git-updater.com or github.com/afragen/git-updater) — this is a separate, standalone plugin. Install it once per site; it will then manage updates for any plugin/theme with the right headers, not just this one. - Install and activate Open Geographies itself (see Installation above).
- That's it. No token is required since this repo is public — Git Updater will pull update metadata anonymously. If you're managing several sites and start hitting GitHub's unauthenticated API rate limit, add a personal access token under Settings → Git Updater → GitHub (any token works for a public repo; no special scopes needed).
Publishing a new version
- Bump
Version:in the open-geographies.php header. - Commit and push/merge to
main(the branch Git Updater is configured to watch — seePrimary Branchabove). - On each site, Plugins → Installed Plugins will show a normal "update available" notice for Open Geographies as soon as Git Updater's next check runs (or trigger it immediately from Dashboard → Updates → Check Again). Click Update Now like any other plugin.
Git Updater compares the Version header of the installed copy against the Version header of the file on main, so an update won't appear until that number actually changes — pushing commits without bumping it does nothing.
How the URL is built
| WordPress page URL | Configured endpoint | API request URL |
|---|---|---|
https://mysite.com/products/blue-widget |
https://api.example.com/v1/pages |
https://api.example.com/v1/pages/blue-widget |
https://mysite.com/about |
https://api.example.com/v1/pages |
https://api.example.com/v1/pages/about |
The plugin takes the last path segment of the current request URI and appends it to your configured base endpoint.
Settings
| Setting | Description |
|---|---|
| API Base Endpoint | Full base URL, e.g. https://api.example.com/v1/pages |
| Request Timeout | Seconds before giving up. Default: 10 |
| Authorization Header Value | Sent as the Authorization HTTP header, e.g. Bearer abc123 |
| Google Maps API Key | Required by [og_map]. Exposed client-side in page source — restrict it by HTTP referrer in the Google Cloud Console. |
| Cache TTL | Seconds to cache responses via WordPress transients. Set to 0 to disable. |
| Custom Error Message | Shown to visitors if the API call fails |
Example API response
The plugin handles mixed JSON payloads — strings, raw HTML, flat arrays, nested objects, boolean flags:
{
"title": "Blue Widget",
"slug": "blue-widget",
"is_published": true,
"status": "active",
"body_html": "<p>This is the <strong>main content</strong> area.</p>",
"intro_html": "<blockquote>A premium product.</blockquote>",
"author": {
"name": "Jane Smith",
"bio": "Senior product writer."
},
"tags": ["widget", "blue", "premium"],
"features": ["Waterproof", "Scratch-resistant", "5-year warranty"],
"meta": {
"seo_title": "Buy Blue Widget | MyStore",
"seo_description": "The best blue widget on the market."
},
"products": [
{ "name": "Blue Widget S", "price": "$9.99", "stock": "In stock" },
{ "name": "Blue Widget M", "price": "$12.99", "stock": "Low stock" },
{ "name": "Blue Widget L", "price": "$15.99", "stock": "Out of stock" }
]
}
Shortcode reference
[og_field] — plain text value
[og_field key="title"]
[og_field key="author.name"]
[og_field key="meta.seo_title" fallback="Untitled"]
key— dot-notation path into the JSONfallback(optional) — text shown when the key is missing
[og_html] — raw HTML from the API
[og_html key="body_html"]
[og_html key="intro_html"]
[og_html key="body_html" read_more="true"]
[og_html key="body_html" read_more="true" read_more_label="Continue reading"]
Rendered through wp_kses_post() — safe HTML tags are preserved, dangerous ones stripped.
read_more(optional) —"true"splits the HTML into<p>paragraphs, shows only the first, and collapses the rest behind a click-to-expand.og-readmore__togglelink. No-ops (returns the full HTML) if there's zero or one paragraph to begin with.read_more_label(optional) — text for the toggle link. Default:"Read more...".
[og_list] — array as <ul> or <ol>
[og_list key="tags"]
[og_list key="features" ordered="true" class="feature-list" item_class="feature-item"]
ordered—"true"for<ol>, default"false"for<ul>class— CSS class on the list element (default:og-list)item_class— CSS class on each<li>
[og_table] — array of objects as <table>
[og_table key="products"]
[og_table key="products" headers="Name,Price,Stock" class="pricing-table"]
headers— comma-separated column labels; defaults to object keys from the first rowclass— CSS class on<table>(default:og-table)
[og_links] — array of objects as a link list
For arrays where each item's link/label live in nested fields - og_list would
JSON-dump the objects as text, and og_table has no way to reach nested fields
for its cells:
[og_links key="resources"]
[og_links key="resources" href_field="link.value" label_field="type.name" label_fallback_field="name"]
Given:
{
"resources": [
{ "name": "Hopewell Baptist - Cemetery", "link": { "value": "https://findagrave.com/..." }, "type": { "name": "Cemetery" } },
{ "name": "Hopewell Baptist - 3D Tour", "link": { "value": "https://matterport.com/..." }, "type": { "name": "3D Tour" } }
]
}
renders a <ul> of <a> links, one per item, skipping any item whose
href_field doesn't resolve to a string.
href_field— dot-notation path within each item to the URL (default:link.value)label_field— dot-notation path within each item to the link text (default:name)label_fallback_field(optional) — tried iflabel_fieldis empty/missing before falling back to the URL itselfclass— CSS class on the<ul>(default:og-links)item_class(optional) — CSS class on each<li>target— default_blank; settarget=""to open in the same tabfallback— text shown when the key is missing, not an array, or no item resolves a valid href
[og_if] — conditional rendering
[og_if key="is_published"]
This page is live.
[/og_if]
[og_if key="status" equals="active"]
Status badge here.
[/og_if]
[og_if key="is_published" not="true"]
Coming soon…
[/og_if]
equals(optional) — match a specific string valuenot—"true"inverts the condition
[og_json] — debug dump
[og_json]
[og_json key="meta"]
[og_json key="author"]
Renders a <pre> block with pretty-printed JSON. Remove from production templates.
[og_gallery] — scrollable thumbnail strip + GLightbox
[og_gallery key="photographs"]
[og_gallery key="photographs" loop="false" navigation="false"]
Renders a plain horizontally-scrollable strip of thumbnails — no carousel library, just CSS overflow-x plus two scroll-arrow buttons that page the strip by roughly one screenful at a time. No template markup or inline `