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

This site is temporarily in read-only mode and not accepting new answers.

Not the answer you're looking for? Browse other questions tagged .