Geo Conditions
Geolocation-based element conditions, dynamic data tags, and geo-targeted content blocks. Cache-safe via AJAX. Built for Bricks Builder.
by Nahnu Plugins · github.com/jaimealnassim/wp-geo-conditions · website
Install
No release zip yet. The repository archive installs, but the folder name will carry the branch suffix and updates will not flow:
wp plugin install https://github.com/jaimealnassim/wp-geo-conditions/archive/refs/heads/main.zipGeolocation-based element conditions, dynamic data tags, and geo-targeted content blocks for WordPress.
Built first-class for Bricks Builder — with full support for Element Conditions, Dynamic Data tags, and a cache-safe AJAX content system that works with any page cache plugin.
Features
- 🌍 Bricks Element Conditions — show/hide elements by country, region, or city
- 🏷️ Bricks Dynamic Tags —
{geo_country},{geo_city},{geo_content:slug}, and more - 📦 Geo Content Blocks — CPT-based geo-targeted content with country rules and a fallback
- ⚡ Cache-safe AJAX — works with WP Rocket, LiteSpeed, W3TC, and any full-page cache
- 🔍 Smart detection chain — Cloudflare → Bunny.net → IP2Location.io (configurable priority)
- 🍪 Cookie caching — visitor geo is stored in a browser cookie, skipping detection on repeat loads
- 🌐 Searchable country picker — Select2 multi-select with all 195 countries
Detection Chain
Geo is resolved in priority order (configurable in Settings):
| Priority | Source | How |
|---|---|---|
| 1 | Cloudflare | CF-IPCountry, CF-Region, CF-IPCity headers |
| 2 | Bunny.net CDN | CDN-PullZone-Country and related headers |
| 3 | IP2Location.io | Remote API (free tier: 30,000 queries/month) |
Results are cached as WordPress transients (per IP) and as a browser cookie, so detection runs at most once per visitor per session.
Best setup: If you're on Cloudflare (even the free plan), no API key is needed. Geo headers are added automatically.
Bricks Builder Integration
Element Conditions
Go to any element → Conditions → add a condition set → select the Geolocation group.
| Condition Key | Comparators | Example Value |
|---|---|---|
geo_country |
is, is not, is one of, is not one of | KW or US,CA,GB |
geo_region |
is, is not, contains, does not contain | California |
geo_city |
is, is not, contains, does not contain | London |
⚠️ Bricks evaluates element conditions server-side on initial render. For cached sites, use the AJAX approach below.
Dynamic Data Tags
Use in any Bricks text, heading, or dynamic data field:
{geo_country} → KW
{geo_country_name} → Kuwait
{geo_region} → Al Ahmadi
{geo_city} → Ahmadi
{geo_source} → cloudflare
{geo_content:my-slug} → rendered geo content block HTML
Geo Content Rules
Go to Geo Conditions → Content Rules → Add New.
Each rule set has:
- A slug used in shortcodes and dynamic tags
- An ordered list of rules, each with selected countries and HTML content
- Rules are evaluated top-to-bottom — first country match wins
- The first row is always the Default / Fallback — shown when no rule matches
Rendering content blocks
PHP (not cache-safe):
[geo_content id="homepage-banner"]
AJAX (cache-safe, recommended):
[geo_content id="homepage-banner" ajax="1" placeholder="Loading…"]
[geo_content_ajax id="homepage-banner" placeholder="Loading…"]
HTML data attribute (cache-safe, works anywhere):
<div data-geo-content="homepage-banner"></div>
Cache-Safe AJAX System
geo-loader.js runs immediately on page load and:
- Checks the browser cookie — if fresh and no dynamic elements, skips AJAX entirely
- Collects all
[data-geo-content]and[data-geo-condition]elements on the page - Fires a single batched POST to
admin-ajax.php - Swaps in content HTML and applies show/hide visibility
Because admin-ajax.php is always excluded from page caches, this works transparently with any caching setup.
Element visibility via data attribute
<!-- Show only for US visitors -->
<div data-geo-condition='{"type":"country","compare":"==","value":"US"}'>
US-only content
</div>
<!-- Hide for a list of countries -->
<div data-geo-condition='{"type":"country","compare":"not_in","value":"DE,FR,IT"}'>
Non-EU content
</div>
<!-- Region-based -->
<div data-geo-condition='{"type":"region","compare":"contains","value":"California"}'>
California content
</div>
JS events
// Fires when a geo content block is populated
el.addEventListener('geoContentLoaded', e => {
console.log('Geo:', e.detail.geo);
});
// Fires when visibility is resolved
el.addEventListener('geoVisibilityResolved', e => {
console.log('Visible:', e.detail.visible);
});
Shortcodes
| Shortcode | Description |
|---|---|
[geo_content id="slug"] |
PHP render (not cache-safe) |
[geo_content id="slug" ajax="1"] |
AJAX render (cache-safe) |
[geo_content_ajax id="slug" placeholder="…"] |
Explicit AJAX wrapper |
[geo_country] |
Visitor country code (e.g. US) |
[geo_country_name] |
Visitor country name |
[geo_region] |
Visitor region/state |
[geo_city] |
Visitor city |
PHP API
// Global helper — get full geo array
$geo = geo_conditions_get_geo();
// [
// 'country_code' => 'KW',
// 'country_name' => 'Kuwait',
// 'region' => 'Al Ahmadi',
// 'city' => 'Ahmadi',
// 'source' => 'cloudflare',
// ]
// Direct class access
$code = \GeoConditions\Geo_Detector::instance()->get_country_code();
$city = \GeoConditions\Geo_Detector::instance()->get_city();
Settings
Geo Conditions → Settings
- Detection priority — drag to reorder Cloudflare / Bunny / IP2Location
- IP2Location API key — free at ip2location.io, 30k queries/month
- Server cache duration — transient TTL per IP (default: 60 minutes)
- Browser cookie duration — how long the geo cookie is kept (default: 24 hours)
- Debug mode — shows a geo info bar at the bottom of every page (admins only)
- Flush cache — clears all server-side transients instantly
Requirements
| WordPress | 6.3 or later |
| PHP | 8.1 or later |
| Bricks Builder | 1.8.4 or later (for Conditions API) |
Bricks Builder is optional — all other features (shortcodes, AJAX content, data attributes) work with any theme or builder.
Installation
- Upload the
geo-conditionsfolder to/wp-content/plugins/ - Activate via Plugins → Installed Plugins
- Go to Geo Conditions → Settings
- Set your detection priority and (optionally) your IP2Location API key
- Create your first content rule at Geo Conditions → Content Rules
File Structure
geo-conditions/
├── geo-conditions.php Bootstrap, constants, autoloader
├── readme.txt WordPress.org readme
├── README.md This file
├── includes/
│ ├── class-geo-detector.php Detection chain + cookie/transient cache
│ ├── class-geo-cache.php Transient cache manager
│ ├── class-ajax-handler.php AJAX endpoint (content + visibility)
│ ├── class-geo-content-manager.php Geo Content CPT, rules, rendering
│ ├── class-bricks-conditions.php Bricks Element Conditions integration
│ ├── class-bricks-dynamic-tags.php Bricks Dynamic Data tags
│ ├── class-elementor-integration.php Elementor dynamic tags
│ ├── class-shortcode.php Shortcode handlers
│ └── class-settings-page.php Admin settings UI
└── assets/
├── js/geo-loader.js Frontend AJAX loader
├── js/geo-admin.js Admin JS utilities
├── css/geo-conditions.css Frontend CSS (loading states)
└── css/geo-conditions-admin.css Admin CSS
Builder Support
| Builder | Conditions | Dynamic Tags | AJAX Content |
|---|---|---|---|
| Bricks Builder | ✅ Full | ✅ Full | ✅ Full |
| Elementor | — | ✅ Tags | ✅ Full |
| Gutenberg | — | via shortcode | ✅ Full |
| Any theme/builder | — | via shortcode | ✅ via data attr |
License
GPL-2.0-or-later
Built by Nahnu Plugins