Why Your WordPress Site Redirects to Spam Sites (And How to Find What’s Doing It)
Quick answer: A WordPress site that redirects visitors to spam (but not you) is a conditional redirect injection. The redirect hides in one of six places: .htaccess, wp-config.php, theme functions.php, wp_options, wp_posts, or a modified active-plugin file. Find it by viewing source before the redirect fires, testing with curl using a Googlebot user-agent and referrer, and checking the database for injected <script> tags. After removal, rotate credentials and patch the entry point (usually an outdated plugin) or the attacker returns in two weeks.
Your site loads fine when you’re logged in. A visitor from Google lands on it and gets thrown to some pharmacy spam page. Maybe only mobile users get redirected. Maybe it only triggers every third visit.
That pattern is not a cache issue. It’s a conditional redirect injection, and it’s one of the most common WordPress compromises of the last five years. The attacker makes sure logged-in admins see a clean site, because if you saw the redirect yourself, you’d fix it.
The whole point is for you not to notice.
Nova Heaven Threat Analysis
Here’s where the redirect is actually hiding.
1. Injected .htaccess Rules
The most common one. Attackers append a RewriteCond block that redirects based on referrer (only Google traffic) or user-agent (only mobile).
Open .htaccess in the WP root. Look for any RewriteCond %{HTTP_REFERER} or RewriteCond %{HTTP_USER_AGENT} block that isn’t yours. Legitimate WordPress .htaccess is short, about 11 lines. Anything beyond that deserves a look.
Don’t just delete the whole file. Replace it with the default WordPress rules from the Codex.
2. Modified wp-config.php
Attackers sometimes add a PHP redirect at the top of wp-config.php, guarded by a cookie or IP check so admins are skipped.
Look at the first 20 lines of wp-config.php. Anything before <?php should not be there. Anything that looks like if (!isset($_COOKIE['wordpress_logged_in_...'])) { header('Location: ...'); } is your culprit.
3. The Theme’s functions.php
Every compromise I’ve investigated where the redirect only affected search-engine referrals had a wp_head hook inside functions.php outputting a <script> tag with a referrer check.
Look for any function in functions.php that references document.referrer, window.location, or location.href. None of that belongs in a PHP file shipped with a theme.
4. Database: wp_options
The attacker’s favorite hiding spot in the last two years.
They inject a redirect script into the siteurl or home option, or create a new option that auto-loads on every page.
SELECT option_name, option_value FROM wp_options WHERE option_value LIKE '%<script%';
If anything returns, that’s it. Don’t edit the row blindly. Note the option name, look up what it’s supposed to contain, and set it back to that value.
5. Database: wp_posts
Injected into post content. Every post gets a <script> tag prepended to it. Renders on every page.
SELECT ID, post_title FROM wp_posts WHERE post_content LIKE '%<script%src=http%';
A common pattern is for the script source to be a lookalike domain like gogleanaiytics.com or jquerry.com, designed to blend in during a quick review.
6. Injected Plugin Files
Rare but real. The attacker modifies one file inside an active plugin, usually the main plugin file or an include that runs on every load, and adds a redirect.
Diff every active plugin against a fresh download from WordPress.org. Anything that doesn’t match got modified.
How to Figure Out Which One It Is
Don’t guess. Reproduce the redirect once in a controlled way, then narrow down.
Step 1. Open the site in an incognito window. If the redirect still happens, it’s session-independent. If it doesn’t, open the site from a different device or network.
Step 2. View source as the page starts loading. Hit Escape or Stop fast enough and you’ll see the HTML before the redirect fires. The redirect is almost always in the first 5KB. What you see there tells you where it lives. A <script> tag or a <meta http-equiv="refresh"> points at the database or a PHP hook. Nothing visible in the HTML before the redirect means the redirect is happening at the HTTP layer.
Step 3. If it’s in the HTML, check options and posts first, then the theme’s functions.php.
Step 4. If it’s at the HTTP layer, check .htaccess and wp-config.php.
Step 5. Test with curl to isolate the trigger:
curl -sI -A "Googlebot" -e "https://google.com" https://yoursite.com/
If that returns a 301 or 302 to a spam domain, your redirect is user-agent or referrer conditional. That narrows it to .htaccess or a theme wp_head hook.
After You Find It
Fixing the symptom is half the work.
The attacker got in somehow, usually through a known vulnerability in an outdated plugin, a weak admin password, or a compromised hosting account.
Rotate all credentials. Rotate the WP salts. Update every plugin and theme to current. Remove anything you aren’t actively using. Turn on 2FA for admins.
If you skip the hardening and just delete the injection, you’ll be back here in two weeks.
What Doesn’t Fix It
Clearing the cache doesn’t fix it. The redirect is in your files or database, not your cache.
Changing your admin password alone doesn’t fix it. The backdoor doesn’t need your password.
Reinstalling WordPress without diffing first doesn’t fix it. The injection is in content you don’t want to lose.
Installing a security plugin after the fact doesn’t fix it either. Scanners find infections. They don’t surgically remove the specific injection without also missing the backdoor that dropped it.
The fix is to find where the redirect lives, remove it, then rotate everything and harden the site so whoever put it there can’t walk back in. A couple of hours of careful work, done in the right order.
Nova Scan’s free version detects conditional redirect injections across all six of the locations above (.htaccess, wp-config, functions.php, options, posts, plugins) in one pass. nova scan overview.
~ SephX, Nova Heaven. A redirect you can’t see is one written specifically to make sure you can’t see it.