1

I want to move my domain from example.com to example.dev and also set a wildcard forward. I use WordPress for blogging, now I want all posts and pages to be moved to the new address but I want some pages to remain accessible with my previous address. For example:

example.com/post -> example.dev/post
example.com/post2 -> example.dev/post2
[all posts be redirected]
example.com/page1 -> example.dev/page1
example.com/page2 -> example.dev/page2
[all pages be redirected]

Exceptions:
example.com/pageN -> example.com/pageN (remain Same URL)
example.dev/pageN -> example.com/pageN (redirected to previous domain)
example.com/PageX -> accessible from both domains

I want both URLs to be used on a same WordPress installation, but some URLs (posts and pages) should be previewed on one domain and some on another and some on both, as explained.

If there's a way to give posts and some pages URL of domain 2 and give the rest domain 1 it would be awesome. Like, instead of forwarding pages and posts, just rewriting their URL. For example, all posts now are on domain example.dev by default but also listed on example.com.

I don't know how to explain this exactly.

Here's my current .htaccess file:

# Prevent rewritten requests (to the WP front-controller) from being redirected
RewriteCond %{ENV:REDIRECT_STATUS} .
RewriteRule ^ - [L]

# The TARGET_DOMAIN environment variable holds the desired target domain (if any)
#  - for the requested URL
# eg. "example.com" or "example.dev" or empty for no redirect / accessible from both.

# Set the "default" target domain
#  - Any URLs not listed below will redirect to this domain
RewriteRule ^ - [E=TARGET_DOMAIN:arhnotes.com]

# URLs that should be redirected to (or remain at) the other domain
RewriteCond %{REQUEST_URI} ^/bio [OR]
RewriteCond %{REQUEST_URI} ^/pages [OR]
RewriteCond %{REQUEST_URI} ^/computing [OR]
RewriteCond %{REQUEST_URI} ^/contact [OR]
RewriteCond %{REQUEST_URI} ^/donate [OR]
RewriteCond %{REQUEST_URI} ^/encrypt [OR]
RewriteCond %{REQUEST_URI} ^/genderless-pronouns [OR]
RewriteCond %{REQUEST_URI} ^/gnu-linux-controversy [OR]
RewriteCond %{REQUEST_URI} ^/legal [OR]
RewriteCond %{REQUEST_URI} ^/readings [OR]
RewriteCond %{REQUEST_URI} ^/now
RewriteRule ^ - [E=TARGET_DOMAIN:alirezahayati.com]

# URLs that should not be redirected - accessible from both domains
#  - Sets TARGET_DOMAIN to empty string (ie. no target domain)
RewriteCond %{REQUEST_URI} ^/login [OR]
RewriteCond %{REQUEST_URI} ^/admin [OR]
RewriteCond %{REQUEST_URI} ^/wp-admin [OR]
RewriteCond %{REQUEST_URI} ^/wp-login [OR]
RewriteCond %{REQUEST_URI} \.(php|css|js|jpg|gif|webp)$ [NC,OR]
RewriteCond %{REQUEST_FILENAME} -f
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^ - [E=TARGET_DOMAIN]

# Redirect to the desired TARGET_DOMAIN (if any)
#  - if not already at the TARGET_DOMAIN
RewriteCond %{ENV:TARGET_DOMAIN} .
RewriteCond %{HTTP_HOST}@@%{ENV:TARGET_DOMAIN} !^([a-z0-9.-]+)@@\1$
RewriteRule ^ https://%{ENV:TARGET_DOMAIN}%{REQUEST_URI} [R=302,L]

# BEGIN WordPress
# The directives (lines) between "BEGIN WordPress" and "END WordPress" are
# dynamically generated, and should only be modified via WordPress filters.
# Any changes to the directives between these markers will be overwritten.
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f [OR]
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>

# END WordPress

ErrorDocument 403 /403.html
ErrorDocument 404 /404.html
ErrorDocument 503 /503.html

A huge thanks and shoutout to Mr. White for the great answer and help. Thanks a lot.

1 Answer 1

0

You could do something like the following at the top of your .htaccess file, before the WordPress front-controller:

# Prevent rewritten requests (to the WP front-controller) from being redirected
RewriteCond %{ENV:REDIRECT_STATUS} .
RewriteRule ^ - [L]

# Redirect everything from "example.com" to "example.dev"
# Except for certain URLs that should stay at .com
RewriteCond %{HTTP_HOST} ^(www\.)?example\.com [NC]
RewriteCond %{REQUEST_URI} !^/pageA-to-stay-at-com
RewriteCond %{REQUEST_URI} !^/pageB-to-stay-at-com
RewriteCond %{REQUEST_URI} !^/pageC-to-stay-at-com
RewriteRule ^ https://example.dev%{REQUEST_URI} [R=302,L]

# Redirect certain URLs from "example.dev" to "example.com"
#  - That should stay at .com (not .dev)
RewriteCond %{HTTP_HOST} ^(www\.)?example\.dev [NC]
RewriteCond %{REQUEST_URI} ^/pageA-to-stay-at-com [OR]
RewriteCond %{REQUEST_URI} ^/pageB-to-stay-at-com [OR]
RewriteCond %{REQUEST_URI} ^/pageC-to-stay-at-com
RewriteRule ^ https://example.com%{REQUEST_URI} [R=302,L]

Note the ! (negation) prefix on the CondPatterns in the first rule block. This makes the condition successful only when the URL does not match. However, in the second rule block (no ! prefix), the requested URL must match one of the stated URLs in order to be redirected back to .com.

Test first with 302 (temporary) redirects and only change to 301 (permanent) - if that is the intention - once you have confirmed everything is working OK. This is to avoid potential caching issues.


Another (better) approach, avoiding repetition of the URLs:

# Prevent rewritten requests (to the WP front-controller) from being redirected
RewriteCond %{ENV:REDIRECT_STATUS} .
RewriteRule ^ - [L]

# Set an environment variable STAY_AT_COM if the requested URL 
# is one of those that should stay at the .com domain
RewriteCond %{REQUEST_URI} =/pageA-to-stay-at-com [OR]
RewriteCond %{REQUEST_URI} =/pageB-to-stay-at-com [OR]
RewriteCond %{REQUEST_URI} =/pageC-to-stay-at-com
RewriteRule ^ - [E=STAY_AT_COM:yes]

# Nothing to change below here except for the domain names...

# Redirect everything from "example.com" to "example.dev"
# Except for the URLs that should stay at .com
RewriteCond %{HTTP_HOST} ^(www\.)?example\.com [NC]
RewriteCond %{ENV:STAY_AT_COM} !yes
RewriteRule ^ https://example.dev%{REQUEST_URI} [R=302,L]

# Redirect URLs back from "example.dev" that should stay at .com
RewriteCond %{HTTP_HOST} ^(www\.)?example\.dev [NC]
RewriteCond %{ENV:STAY_AT_COM} yes
RewriteRule ^ https://example.com%{REQUEST_URI} [R=302,L]

I've changed the conditions in the first rule block to exact string matches (= prefix), rather than regex (that were missing the end-of-string anchor). This shouldn't make much difference with the URLs you are using, but it is easier to enter and avoids potential conflicts in the future.


UPDATE: I'd overlooked that some URLs need to be accessible from both domains and not redirected. The above would redirect to one or the other (two-state). You need triple-state... one or the other or both.

Try the following instead (at the top of the .htaccess file):

# Prevent rewritten requests (to the WP front-controller) from being redirected
RewriteCond %{ENV:REDIRECT_STATUS} .
RewriteRule ^ - [L]

# The TARGET_DOMAIN environment variable holds the desired target domain (if any)
#  - for the requested URL
# eg. "example.com" or "example.dev" or empty for no redirect / accessible from both.

# Set the "default" target domain
#  - Any URLs not listed below will redirect to this domain
RewriteRule ^ - [E=TARGET_DOMAIN:example.dev]

# URLs that should be redirected to (or remain at) the other domain
RewriteCond %{REQUEST_URI} ^/bio [OR]
RewriteCond %{REQUEST_URI} ^/computing [OR]
RewriteCond %{REQUEST_URI} ^/contact [OR]
RewriteCond %{REQUEST_URI} ^/donate [OR]
RewriteCond %{REQUEST_URI} ^/encrypt [OR]
RewriteCond %{REQUEST_URI} ^/genderless-pronouns [OR]
RewriteCond %{REQUEST_URI} ^/gnu-linux-controversy [OR]
RewriteCond %{REQUEST_URI} ^/legal [OR]
RewriteCond %{REQUEST_URI} ^/readings [OR]
RewriteCond %{REQUEST_URI} ^/now
RewriteRule ^ - [E=TARGET_DOMAIN:example.com]

# URLs that should not be redirected - accessible from both domains
#  - Sets TARGET_DOMAIN to empty string (ie. no target domain)
RewriteCond %{REQUEST_URI} ^/login [OR]
RewriteCond %{REQUEST_URI} ^/admin [OR]
RewriteCond %{REQUEST_URI} ^/wp-admin [OR]
RewriteCond %{REQUEST_URI} ^/wp-login [OR]
RewriteCond %{REQUEST_URI} \.(php|css|js|jpg|gif|webp)$ [NC,OR]
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^ - [E=TARGET_DOMAIN]

# Redirect to the desired TARGET_DOMAIN (if any)
#  - if not already at the TARGET_DOMAIN
RewriteCond %{ENV:TARGET_DOMAIN} .
RewriteCond %{HTTP_HOST}@@%{ENV:TARGET_DOMAIN} !^([a-z0-9.-]+)@@\1$
RewriteRule ^ https://%{ENV:TARGET_DOMAIN}%{REQUEST_URI} [R=302,L]

Additional explanation:

RewriteCond %{REQUEST_URI} ^/bio [OR]

I've gone back to using a regular expression (regex) match. This gives you greatest flexible at the expense of additional complexity (although you can mix the two). The above matches any URL that starts with /bio. So, it will also match /bio/ and /bioanything. Use an end-of-string anchor ($) to match /bio only. eg. ^/bio$.

Using a regex will be required to avoid redirecting any URL that starts /wp-admin.

RewriteCond %{ENV:TARGET_DOMAIN} .
RewriteCond %{HTTP_HOST}@@%{ENV:TARGET_DOMAIN} !^([a-z0-9.-]+)@@\1$
RewriteRule ^ https://%{ENV:TARGET_DOMAIN}%{REQUEST_URI} [R=302,L]

The first condition ensures we only try to redirect when there is a target domain set. The second condition checks to see whether the currently requested domain (ie. the Host header) is different to the TARGET_DOMAIN. If both of these checks are successful then it redirects to the target domain on the same URL.

As before, make sure your browser cache is clear before testing and test with a 302 (temporary) redirect to avoid potential caching issues.

30
  • Thanks a lot for your time but none of the solutions you provided work. There's no redirect. I should mention again that both domains are being used on same WordPress installation.
    – ARH
    Nov 6, 2020 at 19:19
  • Please edit your question to include the updated .htaccess file.
    – MrWhite
    Nov 6, 2020 at 19:22
  • I did not understand. Include what updated .htaccess file? Should I put my current htaccess file there?
    – ARH
    Nov 6, 2020 at 19:23
  • Presumably you've added the directives above to your root .htaccess file, changing the necessary URLs and domain names ... please edit your question to include your complete .htaccess file so I can check it. Conflicts with existing directives is a common problem - order is important.
    – MrWhite
    Nov 6, 2020 at 19:25
  • 1
    You're amazing. Thanks a lot man. I really appreciate all your help and effort and time. Thanks. It's perfect.
    – ARH
    Nov 7, 2020 at 10:58

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.