1

I've created a custom post type for my landing pages, which each sit at www.mydomain.com/lp/<page-name>/

I want to keep those custom posts there, so they show up with proper featured images and excerpts on archive and search pages. However, in some cases, if someone goes to a specific page, I want it to load a static page, and associated style sheets and scripts from the directory where the static page is.

So, imagine the following URI hierarchy:

www.mysite.com/lp/page-a/
                 /page-b/   // this page exists in WP for search/archive purposes
                 /page-c/

The above pages all exist in WordPress and work fine. Now, there could be a directory structure on the server like

/vhost/mysite/www/wp-content
                 /wp-includes
                 /foo/page-b.html
                     /page-b.css
                     /public/page-b.js

If someone navigates to /lp/page-x/, if page-x.html exists in /foo, I want it to load that, and I want relative references internal to page-x.html (e.g., <script id="page-x-js" src="./public/page-x.js" defer></script>) to pull from that directory path. But if they go to www.mysite.com/lp/page-a/ and /vhost/mysite/www/foo/page-a.html doesn't exist, I want WordPress to load the normal, internal custom post.

The directory structure doesn't really matter — I have full control over the server. And while I assume this is some .htaccess magic, I'm running Apache and can make changes to the config, or I could even add code to my plugin that creates the custom pages.

Anyone know how I can accomplish this?

3
  • "If someone navigates to /page-x/" - Presumably you mean /lp/page-x/? Presumably <script id="page-x-js" src="./public/page-x.js" defer></script> does not exist in the WordPress generated page?
    – MrWhite
    Jul 6, 2022 at 23:27
  • Yes, on both counts. I meant /lp/page-x/, and will update it in the post. Said script will not exist in the generated page, though other relative paths which don't start with . may exist in both. Jul 7, 2022 at 5:18
  • Actually, thinking through it some more, probably other relative paths won't exist. Jul 7, 2022 at 5:25

1 Answer 1

1

There are two issues here:

  1. Sending the request to /foo/page-x.html if it exists.
  2. Overriding the relative URL-paths to your static resources.

Normally, when rewriting the URL in this way (to different path depths) you should not be using relative URL-paths to your static resources, since the browser naturally resolves this relative to the URL-path displayed in the browser (this is not a file-path). However, if we know what URL-path is being requested and what file-path it should correspond to (as we appear to know in this case) then we can potentially override/correct this with additional rewrite(s) in .htaccess. If the same relative URL-path is used from different URLs then this becomes increasingly difficult to resolve as you would need to hardcode each possibility. Normally you should be using root-relative (or absolute) URL-paths to static resources to avoid this conflict/ambiguity.

The "problem" with the relative URL-path is that when requesting /lp/<page-name>/, a relative URL-path of the form ./public/page-x.js is resolved as /lp/<page-name>/public/page-x.js by the browser. So we need to rewrite this to /foo/public/page-x.js.

These rules need to go near the top of your .htaccess file located at /vhost/mysite/www/.htaccess (which I assume is the document root). Importantly, this needs to go before the WordPress code block (ie. before # BEGIN WordPress).

# 1. Rewrite "/lp/<page-name>/" to "/foo/<page-name>.html" if it exists
RewriteCond %{DOCUMENT_ROOT}/foo/$1.html -f
RewriteRule ^lp/([\w-]+)/$ /foo/$1.html [L]

# 2. Rewrite "relative" static resources
RewriteCond %{DOCUMENT_ROOT}/foo/$1 -f
RewriteRule ^lp/[\w-]+/([\w/-]+\.\w{2,5})$ /foo/$1 [L]

As denoted by the subpattern [\w-]+, I'm assuming <page-name> can consist of just the characters a-z, A-Z, 0-9, _ (underscore) and - (hyphen).

UPDATE: I've removed public/ from the RewriteRule pattern and included a slash (/) in the character class so to match any relative URL-path. It is advisable to keep the \.\w{2,5} part in order to avoid matching "too much". We only want to match actual file requests (that contain a file extension), not literally anything.

2
  • 1
    Awesome! I had to fiddle a little bit to get it to work: the second RewriteCond needs to check in the foo dir: RewriteCond %{DOCUMENT_ROOT}/foo/$1 -f. And the rewrite rule to generate the $1 should match anything (so it gets the /foo/page-b.css, in addition to the public stuff: RewriteRule ^lp/[\w-]+/(.*)$ /landing-page/$1 [L]. I already upvoted, but if you want to make those changes, I'll mark as correct. Jul 8, 2022 at 7:12
  • 1
    @philolegein Sorry, I missed the foo on the RewriteCond directive! I've also removed public/ so that it matches any relative URL-path (need to also add a slash to the character class in that case). Rather than literally matching anything (ie. (.*)) it is still advisable to be more restrictive with the regex and match actual files (that contain a file extension). I've updated my answer.
    – MrWhite
    Jul 8, 2022 at 8:44

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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