How to show the same content on multiple URLs?

A client currently has a website set up with three distinct sub-sites (run off a single WordPress install), each with a slightly different theme (same layout, different colour scheme.

I currently have it set up so each sub-site is a page, with all of it’s pages as children. The header.php checks which page is the parent and includes the appropriate style.

Read More

The problem comes with pages that are identical throughout the site, which the client wishes to have accessible from each sub-site as a separate page.

For example the about page, should be accessible from /site1/about and /site2/about and use the theme for the site that has requested it, but display the same content on both.

I could just create the child pages, and set the rel=”canonical” to reference the original, but from a maintenance point of view, it would preferable to have a single page that the content is pulled from on each of the sub sites.

And so to the question, how do I get several URLs/pages to pull their content from a single source?

EDIT:
Here’s an example of the desired structure:

  • www.example.com – Displays links to
    the three main services, as well as
    general information
  • www.example.com/about – Displays information about the client, styled to match www.example.com
  • www.example.com/service1 – Displays navigation related to the specific service,
    styled in it’s own individual colour,
    alongside generic links (about,
    contact)
  • www.example.com/service1/about – Displays the navigation and stylesheet for /service1, but using the content from www.example.com/about (and with a canonical link reference to www.example.com/about)

This is then repeated for /service2 and /service3.

Related posts

Leave a Reply

1 comment

  1. I’m still struggling with the exact requirements but if I understand correctly I think you can do to accomplish your goals if you use the code I provide you below and then do the following:

    1. Create a page for each of your services (which it sounds like you have already done): /service1/, /service2/, etc.

    2. Create a “base” service page, with a URL of /base-service/; don’t worry, nobody will ever see this on the outside of the website.

    3. Assign /base-service/ as the parent (or grandparent) page for all the “virtual shared” child pages you want replicated under each service.

    4. Create any service specific pages that you also might want to have and assign them to the proper page (i.e. “Service 2”, for example.)

    5. Create a page template in your theme for your services called page-service.php and make sure each of your service pages uses that page template (this is needed so we can identify which of your pages are meant to be services).

    So here’s the code for a class that I called Yoursite_SharedChildPages which you can store in your theme’s functions.php file, or in a .php file of a plugin that you might be writing for your site:

    if (!class_exists('Yoursite_SharedChildPages')) {
      class Yoursite_SharedChildPages {
        // If wanted we could enhance to allow these values to be defined in an 'init' hook
        static $PAGE_TEMPLATE = 'page-service.php';
        static $ABSTRACT_ROOT = 'base-service';
        static function on_load() {
          // Hook 'request' to route the request correctly
          add_filter('request',array(__CLASS__,'request'));
          // Hook 'page_link' to compose URLs correctly
          add_filter('page_link',array(__CLASS__,'page_link'));
        }
        static function request($query_vars) {
          if (!empty($query_vars['pagename'])) {
            // If the page URL rewrite matched meaning WordPress thinks it's a Page
            // Split the URL path by path segments (i.e. by slashes)
            $pagename = explode('/',$query_vars['pagename']);
            if ($pagename[0] == self::$ABSTRACT_ROOT) {
              // If the first path segment is the abstract root we care about
              if (count($pagename)==1) {
              // Don't allow anyone to visit this abstract root page
                $pagename = array('#'); // An invalid page name, so it will 404
              } else {
                // If it is a child page in which case redirect to the first service
                // This is important so the user can view the page after they edit it
                $pages = self::get_page_ids_by_template(self::$PAGE_TEMPLATE);
                if (isset($pages[0]) && $page = get_post($pages[0])) {
                  // Assuming we have at least one page with the page template
                  $pagename[0] = $page->post_name;
                  // then redirect to it the first service found.
                  wp_safe_redirect('/'.implode('/',$pagename).'/');
                  exit;
                }
              }
            } else if (count($pagename)>1) {
              // If there are child pages
              if (get_page_by_path($query_vars['pagename'])) {
                // If it is an actual child page then just let it pass thru
              } else {
                  // If a virtual child page then see if parent has the template
                $parent = get_page_by_path($pagename[0]);
                $pages = self::get_page_ids_by_template(self::$PAGE_TEMPLATE);
                if (in_array($parent->ID,$pages)) {
                  // If virtual child of a service page, change parent to the abstract root
                  $pagename[0] = self::$ABSTRACT_ROOT;
                  $query_vars['pagename'] = implode('/',$pagename);
                  // The URL doesn't match a virtual page, will appropriately get a 404
                }
              }
            } else {
              $pagename = false;
            }
          }
          if (is_array($pagename))
            $query_vars['pagename'] = implode('/',$pagename);
          return $query_vars;
        }
        static function get_page_ids_by_template($template) {
          // This can be performance optimized but I wouldn't worry about it 
          // until there is a performance issue
          global $wpdb;
          $sql = "SELECT post_id FROM {$wpdb->postmeta} " . 
                 "WHERE meta_key='_wp_page_template' AND meta_value='%s'";
          return $wpdb->get_col($wpdb->prepare($sql,$template));
        }
        static function page_link($link) {
          $parts = explode('/',$link);
          if ($parts[3]==self::$ABSTRACT_ROOT) {
            // This is really only useful for links in the admin.
            if (!is_admin()) {
              global $wp_query;
              if (!empty($wp_query->query_vars['pagename'])) {
                $pagename = explode('/',$wp_query->query_vars['pagename']);
              }
            } else {
              // If we get a URL that uses the abstract root, assign it the first service.
              $pages = self::get_page_ids_by_template(self::$PAGE_TEMPLATE);
              if (isset($pages[0]) && $page = get_post($pages[0])) {
                // Assuming we have at least one page with the page template
                $parts[3] = $page->post_name;
                // then redirect to it the first service found.
                $link = implode('/',$parts);
              } else {
                $link = preg_replace('#^(https?://[^/]+)(/.*)$#','$1',$link);
              }
            }
          }
          return $link;
        }
      }
      Yoursite_SharedChildPages::on_load();
    }
    

    And here are some screenshots that can illustrate the steps mentioned above:




    Let me know if this is not what you were looking for and/or if you run into something that needs to be addressed by this solution in addition to what I have coded. Good luck!