Home » WordPress » Generate Directory Pages from SEO Metadata
Improve WordPress Site Security by Blocking Xmlrpc
An effective way to improve wordpress site security by blocking xmlrpc with redirect permanent directives in Apache Server configuration.

Generate Directory Pages from SEO Metadata

For improved navigability of sites it is beneficial to generate directory pages of articles sourced from metadata for search engine optimization (SEO). Generally it’s a matter of preference whether to organize articles for WordPress sites into broad categories. Many sites simply place slugs for all pages directly behind their domain name. This approach may help with site rankings as search engines like short URLs. Conversely, a category as part of the path adds search keywords.

classfactory.com/wordpress/generate-directory-pages-from-seo-metadata

For instance, the URL for this article has “/wordpress” as first part of its path. This way, headlines for articles are shorter and the URL still indicates I’m writing about WordPress.

However, in WordPress there is a downside to directory parts in URLs. For all I’m aware, one needs to create a page for each section of the path. And if there’s a page, it can’t just be empty. But no one, certainly not me, likes to write such boring landing pages. Search engines refuse to index them. Yet, users browsing sites may stumble upon such directories when navigating menus.

The solution I’m presenting in this article is to automatically generate landing pages from metadata. Successful sites will have to write page descriptions for SEO anyway, so why not use them for directory pages?

classfactory.com/code

finalgebra.com/algebra

The above quote has two examples for generated pages. The one for classfactory.com/code has entries for an actual subdirectory “/r”. And under finalgebra/algebra you’ll find a landing page with two authored paragraphs and afterwards generated content for “/algebra” and “/interest-rate-calculators”.

Summing up, the proposed plugin code allows combining written content with generated directories from multiple categories. Best of all, after adding new articles, these directories update automatically.

Retrieve Metadata for Page Directories from Database

I’m using Yoast SEO mainly to place metadata tags into my pages. With a little bit of database analysis, I came up with this statement selecting metadata for sub-pages:

select distinct permalink, breadcrumb_title,
description, object_id 
from wp_yoast_indexable 
where post_parent in 
(
  select distinct object_id from 
  wp_yoast_indexable where 
  permalink='https://classfactory.com/r/'
) 
and breadcrumb_title is not null 
and description is not null 
and post_status='publish' order by object_id

This simple SQL statement extracts everything that’s needed for a landing page directory: the full page URI, page title and meta description. The object id orders records for sub-pages of “/r/” in sequence of writing.

Code for a WordPress Plugin to Generate Directory Pages

Having retrieved records for directories from database, it’s straightforward to create a custom WordPress PHP plugin with a shortcode feeding in generated content.

I don’t currently have resources to publish complete plugin code, so a couple of key snippets will have to suffice.

Using a class skeleton[2] for a standard WordPress PHP plugin[1], put the methods below into your class for public functions:

class Directory_Listing_Public {

private function get_full_uri($uripath='') {
  if(isset($_SERVER['HTTPS']) 
        && $_SERVER['HTTPS'] === 'on') {
    $link = "https";
  } else {
    $link = "http";
  }
  $link .= "://";
  $link .= $_SERVER['HTTP_HOST'];
  if (!empty($uripath)) {
    $link .= $uripath;
  } else {
    $link .= $_SERVER['REQUEST_URI'];
  }
  $link = sanitize_url($link);
  return $link;
}

private function get_directory_array($uripath='') {
  $uri = $this->get_full_uri($uripath);
  $uri = esc_url_raw($uri);
  $uriparmidx = strpos($uri,'?');
  if ($uriparmidx > 0) {
    $uri = substr($uri, 0, $uriparmidx);
  }
  global $wpdb;
  $querystring = "select distinct permalink,";     
  $querystring .= " breadcrumb_title,";
  $querystring .= " description, object_id";
  $querystring .= " from wp_yoast_indexable";
  $querystring .= " where post_parent in (";
  $querystring .= "select distinct object_id";
  $querystring .= " from wp_yoast_indexable";
  $querystring .= " where permalink=%s)";
  $querystring .= " and breadcrumb_title is not null";
  $querystring .= " and description is not null";
  $querystring .= " and post_status='publish'";
  $querystring .= " order by object_id";
  $results = $wpdb->get_results(
    $wpdb->prepare($querystring, $uri));
  $child_arr = array();
  foreach ($results as $result) {
    $rv = array('link'=>$result->permalink,
            'title'=>$result->breadcrumb_title,
            'desc'=>$result->description);
    $child_arr[$result->permalink] = $rv;
  };
  return $child_arr;
}

private function get_article_summaries($childarr) {
  $output='';
  // reverse to have newest article first
  $childarr = array_reverse($childarr);
  foreach ($childarr as $ce) {
    $link = $ce['link'];
    $title = $ce['title'];
    $desc = $ce['desc'];
    $template="<h2>\n";
    $template .="<a href=\"$link\">$title</a>\n";
    $template .="</h2>\n";
    $template .="<p>$desc</p>\n";
    $output .= $template;
  }
  return $output;
}

public function directory_listing_shortcode($atts,
    $content = "") {
  try {
    $atts = shortcode_atts(array('uripath' => ''),
      $atts);
    $uripath = $atts['uripath'];
    $array = $this->get_directory_array($uripath);
    $markup = $this->get_article_summaries($array);
    return $markup;
  } catch (Exception $e) {
    // always return!
    $msg = esc_html($e->getMessage());
    return "<p style=\"color:red;\">$msg</p>";
  }
}

// end class Directory_Listing_Shortcode_Public
}

Afterwards, in your plugin definition class under the includes directory of the skeleton, add the hook for the shortcode:

class Directory_Listing {

private function define_public_hooks() {

  $plugin_public = new Directory_Listing_Public( 
     'directory-listing-plugin',
     $this->get_version());

  $this->loader->add_action( 'wp_enqueue_scripts',
     $plugin_public, 'enqueue_scripts' );
  $this->loader->add_shortcode( 'directory-listing',
     $plugin_public, 'directory_listing_shortcode');
}

// end class Directory_Listing
}

Put your plugin into the appropriate plugin directory of your WordPress instance and activate it in the admin menu. You should now be ready to have directories auto-generated.

[directory-listing]

[directory-listing uripath=”/r/”]

Sample shortcode tags for auto-generated directories

The first sample shortcode generates entries for sub-pages of the current page. In contrast, the second sample is for directories for categories other than the current one. So in the case of the “/code/” landing page, I used the second variation. Under the “/wordpress/” page specifying the uripath isn’t necessary.

This concludes the plugin code section to generate directory pages from SEO metadata.

References

[1] Plugin Basics: WordPress.org

[2] WordPress Plugin Skeleton: github.com


Published: December 2, 2022
Updated: December 3, 2022

Classfactory.com
Tech Solutions and Programming