Имате WooCommerce магазин, обслужва клиенти от България и втори домейн, който продава в Румъния. Българските потребители виждат българския домейн и искате да насочите румънксите потребители към румънския сайт.
Проблемът: WordPress трябва да разбере откъде идва всеки посетител, преди да зареди каквото и да било. Повечето geo-redirect плъгини правят точно това – изпълняват PHP логика при всяка заявка, убиват page cache-а и добавят 200-400ms латентност.
Как румънският потребител автоматично попада на румънския домейн, където всичко е на езика и валутата, които очаква? Ще разьгледаме два подхода, които работят добре за тази задача – единият изисква Cloudflare Workers, другият е обикновен PHP snippet директно в WordPress.
Съдържание
Защо плъгините за geo-redirect забавят WooCommerce
Повечето WordPress плъгини за geo-redirect (IP2Location, GeoTargetingWP, Redirection с geo rules) работят на PHP ниво. При всяка заявка WordPress зарежда целия стек – wp-load.php, wp-settings.php, активни плъгини, theme functions – само за да провери IP адреса и да реши дали да пренасочи.
Това поведение прави page caching почти невъзможен. Ако Varnish или LiteSpeed Cache върне кеширана българска страница на румънски потребител, резултатът е грешен. Затова тези плъгини обикновено добавят DONOTCACHEPAGE константа или изключват определени URL-и от кеша. TTFB скача от 150ms на 600-800ms при всяко първо зареждане, защото всяка заявка минава през пълния PHP стек. За магазин, който разчита на добри Core Web Vitals резултати, това е неприемливо.
Двата подхода по-долу избягват тези плъгини изцяло.
Вариант 1: PHP snippet с CF-IPCountry хедър
Това е най-простият работещ вариант. Cloudflare автоматично добавя хедъра CF-IPCountry към всяка заявка, която минава през мрежата. Единственото условие – домейнът да е зад Cloudflare proxy (оранжевото облаче в DNS настройките). Базовата Cloudflare конфигурация отнема 10 минути.
PHP кодът се поставя в functions.php на child темата или в Code Snippets плъгин на българския домейн:
add_action('template_redirect', function() {
if (is_admin() || wp_doing_ajax() || wp_doing_cron()) {
return;
}
if (defined('REST_REQUEST') && REST_REQUEST) {
return;
}
$country = strtoupper(
sanitize_text_field($_SERVER['HTTP_CF_IPCOUNTRY'] ?? '')
);
if ($country === 'RO') {
wp_redirect('https://example.ro', 302);
exit;
}
}, 1);
Приоритетът 1 в add_action е съществен. WordPress изпълнява template_redirect хуковете по приоритет – стойност 1 означава, че пренасочването става преди темата, преди WooCommerce (приоритет 10+), преди аналитичните плъгини. По-малко PHP код се изпълнява, по-бързо идва redirect-ът.
Какво проверява кодът преди пренасочване
is_admin() спира изпълнението за /wp-admin/ заявки. wp_doing_ajax() предпазва AJAX повиквания от WooCommerce количката и checkout формите. wp_doing_cron() изключва WP-Cron задачите. REST_REQUEST константата предпазва REST API endpoint-и, които може да използват други плъгини или мобилни приложения.
Без тези проверки redirect-ът може да счупи admin панела при достъп от румънски IP, да прекъсне AJAX добавянето в количката или да блокира API интеграции.
Ограничения на PHP подхода
PHP snippet-ът изпълнява WordPress частично преди redirect-а. template_redirect се задейства след wp-load.php и wp-settings.php, което означава 50-150ms PHP overhead дори при най-бързия хостинг. За повечето сайтове това е напълно приемливо – потребителят вижда redirect за под 200ms.
По-сериозният проблем е кеширането. Ако сървърът използва full-page cache (Varnish, LiteSpeed, nginx FastCGI), кешираната страница се сервира преди PHP да се задейства. Румънски потребител получава кеширания български HTML вместо redirect. Решението е да се добави Cache-Vary хедър по CF-IPCountry или да се изключат redirect страниците от кеша.
add_action('send_headers', function() {
if (!is_admin()) {
header('Vary: CF-IPCountry', false);
}
});
Този Vary хедър казва на кеш слоя, че отговорът зависи от държавата на потребителя. LiteSpeed и Varnish ще пазят отделни кеш копия за BG и RO трафик. Минусът: кешът става по-голям и по-малко ефективен, защото всяка страница се съхранява в няколко варианта.
Вариант 2: Cloudflare Workers – redirect на edge ниво
Cloudflare Workers изпълнява JavaScript на edge сървъра, най-близо до потребителя, преди заявката да достигне WordPress. Няма PHP overhead. Няма конфликт с page cache. Redirect-ът се случва за под 5ms.
Безплатният план на Workers включва 100 000 заявки на ден – достатъчно за повечето малки и средни магазини.
Създаване на Worker
В Cloudflare Dashboard, секция Workers & Pages, натиснете Create Application и после Create Worker. Дайте описателно име – например geo-redirect-ro. Cloudflare генерира preview URL, но за production Worker-ът ще се свърже с route на българския домейн.
export default {
async fetch(request) {
const url = new URL(request.url);
const country = request.headers.get('CF-IPCountry') || 'XX';
const path = url.pathname;
// Skip assets, admin, API, AJAX
if (
path.startsWith('/wp-admin') ||
path.startsWith('/wp-json') ||
path.startsWith('/wp-content') ||
path.match(/.(js|css|png|jpg|webp|svg|woff2?)$/) ||
url.searchParams.has('wc-ajax')
) {
return fetch(request);
}
// Romanian visitors -> Romanian domain
if (country === 'RO') {
return Response.redirect('https://example.ro' + path, 302);
}
return fetch(request);
}
};
Worker-ът пренасочва с 302 (temporary redirect). 301 би бил кеширан от браузъра и потребител, който пътува между държавите, ще вижда грешния домейн без начин да се коригира.
Route конфигурация
След deploy, в секцията Triggers добавете route: example.bg/*. Worker-ът ще се задейства за всички заявки към българския домейн. wc-ajax проверката в кода предпазва WooCommerce AJAX количката от пренасочване по средата на checkout.
За WooCommerce webhook-ове и API интеграции с ERP или счетоводен софтуер, добавете допълнителни изключения. Webhook URL-ите обикновено минават през /wp-json/wc/v3/, което вече е покрито, но custom endpoint-и може да изискват отделна проверка.
Запазване на потребителския избор с cookie
Автоматичното пренасочване създава проблем: румънски потребител, който иска да поръча от българския магазин (по-ниски цени, различен продуктов каталог), не може да остане на .bg домейна. IP-базираната геолокация не е 100% точна – VPN потребители, корпоративни мрежи и мобилни оператори с routing през друга държава ще получат грешен redirect.
Cookie override механизмът е задължителен.
За PHP варианта, добавете проверка в началото на snippet-а:
add_action('template_redirect', function() {
if (isset($_COOKIE['skip_geo_redirect'])) {
return;
}
if (is_admin() || wp_doing_ajax() || wp_doing_cron()) {
return;
}
if (defined('REST_REQUEST') && REST_REQUEST) {
return;
}
$country = strtoupper(
sanitize_text_field($_SERVER['HTTP_CF_IPCOUNTRY'] ?? '')
);
if ($country === 'RO') {
wp_redirect('https://example.ro', 302);
exit;
}
}, 1);
На фронтенда, language switcher или банер „Искате да останете на българския сайт?“ сетва skip_geo_redirect cookie с JavaScript:
document.cookie = 'skip_geo_redirect=1; max-age=2592000; path=/; SameSite=Lax';
30 дни (2592000 секунди) е разумен баланс – достатъчно дълго, за да не досажда, достатъчно кратко, за да не е постоянно.
За Workers варианта, добавете cookie проверка преди redirect логиката:
const cookies = request.headers.get('Cookie') || '';
if (cookies.includes('skip_geo_redirect=1')) {
return fetch(request);
}
SEO: hreflang и индексиране при два домейна
Google трябва да знае, че .bg и .ro домейните са езикови варианти на един бизнес, а не дублирано съдържание. В head секцията на всяка страница и на двата домейна:
Googlebot обикновено идентифицира себе си с CF-IPCountry: US. Ако нито PHP snippet-ът, нито Worker-ът пренасочва US трафик (а и не трябва), Google ще индексира българския домейн нормално. Румънският домейн ще се индексира самостоятелно от Google Romania.
302 redirect е правилният код за geo-базирано пренасочване. 301 казва на Google „тази страница се е преместила завинаги“, което не е вярно – страницата съществува и на двата домейна.
PHP snippet или Workers: кога кой вариант
PHP вариантът е подходящ, когато сайтът вече е зад Cloudflare, хостингът няма агресивен full-page cache и трафикът е умерен – до 50 000 посещения месечно. Поддръжката е проста: един snippet в functions.php или Code Snippets плъгин, който всеки WordPress разработчик разбира.
Workers вариантът е по-добър за магазини с висок трафик, агресивно кеширане (Varnish, LiteSpeed Enterprise, Cloudflare APO) и нужда от нулев PHP overhead. Redirect-ът се случва преди origin сървъра да разбере, че има заявка. За сайтове, където всяка милисекунда има значение, edge redirect-ът е правилният избор.
И двата варианта работят с WebP оптимизация на изображенията и останалите front-end оптимизации без конфликт. Geo-redirect логиката е напълно независима от rendering pipeline-а.
Тестване без пътуване до Румъния
Curl с custom хедър тества PHP варианта директно:
curl -I -H "CF-IPCountry: RO" https://example.bg/
Очакваният отговор е HTTP 302 с Location: https://example.ro. Ако вместо това получите 200 и HTML съдържание, page cache-ът сервира преди PHP. Изчистете кеша и тествайте отново, или добавете Vary хедъра от секцията за ограничения.
VPN от Румъния дава пълен end-to-end тест – DNS resolution, Cloudflare edge routing, WordPress redirect. Windscribe и ProtonVPN имат безплатни румънски сървъри.
За Workers варианта, Cloudflare Dashboard показва real-time логове в секция Workers > Logs. Всеки redirect се вижда с country code, URL и HTTP status.
Често задавани въпроси
-
Работи ли geo-redirect без Cloudflare?
PHP snippet-ът разчита на CF-IPCountry хедъра, който добавя само Cloudflare. Без Cloudflare е необходима алтернативна geo-IP база (MaxMind GeoLite2), което добавя допълнителна сложност и заявка към база данни при всяко зареждане.
-
302 или 301 redirect за пренасочване по държава?
Винаги 302 (temporary). 301 се кешира от браузъра и казва на Google, че страницата се е преместила завинаги. При geo-redirect и двата URL-а са валидни – просто обслужват различни аудитории.
-
Колко струва Cloudflare Workers за geo-redirect?
Безплатният план включва 100 000 заявки дневно. За повечето малки и средни магазини това е достатъчно. Платеният план е $5/месец за 10 милиона заявки.
-
Какво става с румънски потребител, който иска да купи от българския магазин?
Cookie override механизмът позволява ръчна смяна. Банер или бутон сетва skip_geo_redirect cookie и redirect-ът спира за 30 дни.
-
Ще счупи ли geo-redirect WooCommerce количката?
Не, ако AJAX заявките са изключени от redirect логиката. PHP snippet-ът проверява wp_doing_ajax(), а Workers вариантът филтрира wc-ajax параметъра.