How to Incorporate Humans.txt into Your WordPress Site

How to Incorporate Humans.txt into Your WordPress Site

Have you ever asked yourself “Who made it?” or “How did they make it?” looking at some pretty (or awful) website somewhere on the web. Of course there are plenty of tools to make your guess but what if developers have a straightforward way to sign the work they’ve done even on client sites. That is the case where humans.txt comes in as a simple, legal and unobtrusive solution.

How to Incorporate Humans.txt into Your WordPress Site

What is Humans.txt?

Humans.txt is a quite new initiative started by a Spanish team of enthusiasts to bring a “client-friendly” method for developers to indicate their authorship on a site. The main idea is very simple. Include all information about “humans behind the site” and tools used by them into a plain text file, name it humans.txt and put it in the root of your site (near the robots.txt). That will make it available under the request of http://yourdomain/humans.txt and by providing somewhere on site a link to this file you can make it discoverable.

What is the reason for doing this? When developing sites for clients, especially in the corporate field, it’s not always possible to leave a direct footprint on it. But using humans.txt provides a simple and unobtrusive way to present the information about authors for visitors. Even Google does it, why should we not?

Some Important Questions Before We Start

With this tutorial you will learn how to add dynamically generated humans.txt to the WordPress installation. That means you don’t have to actually create a file, edit and upload it each time you need to make changes. But why is it a better solution? When you’re dealing with just one or a few sites the file is good enough.

However when you have a significant range of clients’ sites to support, keeping all information concise and correct could be an unnecessary pain for such a simple task. So we are going to do it the WordPress way – we are going to make the content of humans.txt generated by our code, make it filterable for some probable future needs and serve it under the appropriate request.

Sounds good, but may be there is a plug-in for that? Of course, the WordPress repository has already had a number of plug-ins to solve this problem. But encapsulating every particular task into a separate plug-in on several sites will have finally led you to an enormous number of plug-ins to watch, keep up to date, test for compatibility with your own code etc. So we will do it ourselves.

Another point worth mentioning is a place to include our code – where should it go? We will not wrap it into a separate plug-in because of the reason mentioned above. So, should we put it into functions.php of the active theme? That’s the simplest option available, but there is a better one.

If you have not already adopted the concept of a custom functionality plug-in to store all your tweaks and customisations for a particular WordPress installation, you should probably familiarise yourself with it, because it’s a significant improvement to a WordPress developer’s workflow. And it’s the most suitable place to include our code.

The Code

Let us first produce a simple plan to understand what we are going to do:

  • generate the content for humans.txt and make it filterable
  • make WordPress recognise a humans.txt request to prevent a 404 error
  • upon request display the generated content instead of loading a template file
  • include a link to humans.txt file in the head section of the site
  • bonus: include humans.txt badge with a link to a file in the footer of the site

We have also a few requirements to check:

  • WordPress has to be installed in the site root (because humans.txt should be in the root)
  • pretty permalinks have to be active in order to use dynamically rewritten URL
/* Generate humans.txt content */
function do_humans() {		
	
//serve correct headers
header( 'Content-Type: text/plain; charset=utf-8' ); 

//let some other plugins do something here
do_action( 'do_humanstxt' ); 

//prepare default content
$content = "
/* TEAM */

Developer: John Doe
Contact: hello [at] johndoe.com
Twitter: @johndoe

/* THANKS */

Indispensable contributor: John's mom
Twitter: @johnsmom

/* SITE */
Language: English
Standards: HTML5, CSS3
CMS: WordPress
";	
	//make it filterable
	$content = apply_filters('humans_txt', $content);
	
	//correct line ends
	$content = str_replace("\r\n", "\n", $content);
	$content = str_replace("\r", "\n", $content);
	
	//output
	echo $content;		
}

/* Link to humans.txt for head section of site */
function frl_humanstxt_link(){
   
$url = esc_url(home_url('humans.txt'));    
echo "<link rel='author' href='{$url}' />";
}

/* Print humans.txt button somewhere on the site */
function frl_humanstxt_button(){	
	
//make sure that this is correct path to button image !!!
$src = esc_url(trailingslashit(plugins_url('', __FILE__)).'humanstxt-isolated-orange.gif');	
$url = esc_url(home_url('humans.txt'));	
echo "<div id='humanstxt-badge'><a href='{$url}'><img src='{$src}' alt='humans.txt' /></a></div>";
}

/* Make WP understand humans.txt url */
function frl_humanstxt_init(){
global $wp_rewrite, $wp;

//root install check
$homeurl = parse_url(home_url());
if (isset($homeurl['path']) && !empty($homeurl['path']) && $homeurl['path'] != '/')
    return;

//check for pretty permalinks
$permalink_test = get_option('permalink_structure');
if(empty($permalink_test))
    return;
    
//register rewrite rule for humans.txt request		
add_rewrite_rule('humans\.txt$', $wp_rewrite->index.'?humans=1', 'top');
        
// flush rewrite rules if 'humans' one is missing
$rewrite_rules = get_option('rewrite_rules');
if (!isset($rewrite_rules['humans\.txt$'])) 
    flush_rewrite_rules(false);
    
//add 'humans' query variable to WP 
$wp->add_query_var('humans');

// display links to humans txt (when it's properly registered)
if(function_exists('frl_humanstxt_link'))
    add_action('wp_head', 'frl_humanstxt_link');
    
if(function_exists('frl_humanstxt_button'))
    add_action('wp_footer', 'frl_humanstxt_button'); 
}
add_action('init', 'frl_humanstxt_init');

/* Conditional tag to check for humans.txt request */
function is_humans(){
       
if( 1 == get_query_var('humans'))
    return true;

return false;
}

/* Load dynamic content instead or regular WP template */
function frl_humanstxt_load(){    
if(is_humans()){
    do_humans();
    die();
}
}
add_action('template_redirect', 'frl_humanstxt_load');

[tut download=”http://cdn.onextrapixel.com/wp-content/uploads/2011/11/humantxt.zip”]

The Explanation

Let us now have a more detailed look at each part of the code.

Template Tags and Content Generation

function do_humans() {		
	
//serve correct headers
header( 'Content-Type: text/plain; charset=utf-8' ); 

//let some other plugins do something here
do_action( 'do_humanstxt' ); 

//prepare default content
$content = "
/* TEAM */

Developer: John Doe
Contact: hello [at] johndoe.com
Twitter: @johndoe

/* THANKS */

Indispensable contributor: John's mom
Twitter: @johnsmom

/* SITE */
Language: English
Standards: HTML5, CSS3
CMS: WordPress
";
	
//make it filterable
$content = apply_filters('humans_txt', $content);

//correct line ends
$content = str_replace("\r\n", "\n", $content);
$content = str_replace("\r", "\n", $content);

//output
echo $content;		
}

Inside do_humans we take care of sending correct headers without output. do_humanstxt action allows us to modify this part in the future. Then we create some default content for displaying and register humans_txt filter hook to allow changes to this content when needed. Then, after taking care of line endings, we output the result.

What information should be included here? Humanstxt.org’s Standard section gives us some basic guidelines and examples, but it’s entirely up to you.

/* TEAM */
Your title: Your name.
Site: email, link to a contact form, etc.
Twitter: your Twitter username.
Location: City, Country.
[...]

/* THANKS */
Name: name or url
[...]

/* SITE */
Last update: YYYY/MM/DD
Standards: HTML5, CSS3,..
Components: Modernizr, jQuery, etc.
Software: Software used for the development

Meanwhile we define two template tags to print humans.txt links on the site:

  • frl_humanstxt_link produces a link for head section with rel="author" attribute;
  • frl_humanstxt_button outputs the graphic badge.
function frl_humanstxt_link(){

$url = esc_url(home_url('humans.txt'));    
echo "<link rel='author' href='{$url}' />";
}

function frl_humanstxt_button(){	
	
//make sure that this is correct path to button image !!!
$src = esc_url(trailingslashit(plugins_url('', __FILE__)).'humanstxt-isolated-orange.gif');	
$url = esc_url(home_url('humans.txt'));	
echo "<div id='humanstxt-badge'><a href='{$url}'><img src='{$src}' alt='humans.txt' /></a></div>";
}

Humans.txt Badges

Humanstxt.org provides us with various graphics to use if possible, so we just download one of them into our functionality plug-in folder (but make sure you use the correct path to this graphic file on your installation). Then we display this file as a linked image:

Humans.txt Isolated Orange

Introducing New URL to WordPress

The frl_humanstxt_init function registers the humans.txt url with WordPress. Let’s explain it step by step.

/root install check
$homeurl = parse_url(home_url());
if (isset($homeurl['path']) && !empty($homeurl['path']) && $homeurl['path'] != '/')
    return;

//check for pretty permalinks
$permalink_test = get_option('permalink_structure');
if(empty($permalink_test))
    return;

First of all we check for the root installation of WordPress by parsing the home URL of our site. Then we also check for the permalink_structure option that stores the structure of the posts’ permanent links. It could be treated as an indicator that “pretty permalinks” are active on our installation, which is an obligatory requirement for our technique.

//register rewrite rule for humans.txt request		
add_rewrite_rule('humans\.txt$', $wp_rewrite->index.'?humans=1', 'top');

When we use pretty permalinks, every requested link on a site – http://yourdomain.com/some_query – is dynamically rewritten by the server into more programmatically obvious form http://yourdomain.com/?query_var=value. The rule that allows WordPress to find a match between “pretty” and “ugly” forms of the same page is a rewrite rule.

Every installation of WordPress generates the set of such rules in a form of regular_expression_to_match => actual_url_to_fetch and stores them into rewrite_rules option. WordPress Rewrite API allows developers to add their own rules to the default set to make WordPress recognise custom URL structures. With add_rewrite_rule function we are doing exactly that. The request http://yourdomain.com/humans.txt will be rewritten as http://yourdomain.com/?humans=1 with our rule.

// flush rewrite rules if 'humans' one is missing
$rewrite_rules = get_option('rewrite_rules');
if (!isset($rewrite_rules['humans\.txt$'])) 
	flush_rewrite_rules(false);

After adding our rewrite rule for the first time we also should force WordPress to regenerate the whole set of rules and write them into the DB for future use. That could be achieved with the flush_rewrite_rules function which, for performance sake, we execute only after checking for the absence of the rule in question in rewrite_rules option.

//add 'humans' query variable to WP 
$wp->add_query_var('humans');

What next? After transforming the requested URL into programmatically understandable form WordPress parses requested variables to make a query to DB and stores the results in a global object $wp (and later $wp_query). If some unknown variable is found it will not be stored and will not be able to affect the query.

To avoid this in our case we register the humans query variable with WordPress using add_query_var method of environmental class WP. After that WordPress will understand this variable and, being requested, it will be stored in environmental objects and will be accessible for other functions. (For further details concerning WordPress parsing mechanism please refer to excellent article by Ozh).

// display links to humans txt (when it's properly registered)
if(function_exists('frl_humanstxt_link'))
    add_action('wp_head', 'frl_humanstxt_link');
    
if(function_exists('frl_humanstxt_button'))
    add_action('wp_footer', 'frl_humanstxt_button');

It’s a good time also to check for the existence of functions for printing the humans.txt link(s) and hook them into wp_header and wp_footer respectively. That allows us to be sure that our links will appear only when humans.txt URL works properly.

add_action('init', 'frl_humanstxt_init');

Finally we hook our frl_humanstxt_init function into init action to be sure that all our modifications will be carried out early enough.

Template Loading

function is_humans(){
if( 1 == get_query_var('humans'))
    return true;

return false;
}

After setting up a rewriting mechanism our code creates is_humans conditional tag to help us determine the humans.txt request. It uses get_query_var function that allows us to retrieve the value of a particular query variable stored in global object $wp_query. Happily we have taken care of that beforehand.

Now, when WordPress can understand the humans.txt request we should force it to load our dynamic content instead of the regular template (to simulate the regular .txt file behaviour). So we interfere in the WordPress process of template loading with our function frl_humanstxt_load.

function frl_humanstxt_load(){
if(is_humans()){
    do_humans();
    die();
   }
}
add_action('template_redirect', 'frl_humanstxt_load');

It uses the previously mentioned is_humans conditional tag to determine the humans.txt request, then it calls to do_humans to output the content. Finally, we hook it into template_redirect action.

And that is all – we have completed our plan. Now on visiting http://yourdomain.com/humans.txt URL people should see something like this:

Final Output

Conclusion

This tutorial has demonstrated how you can use the power of WordPress APIs, actions and filters to introduce a completely new URL to the system, make the dynamically generated content appear there simulating the behaviour of the simple .txt file. And all that we perform to support fresh and friendly initiative stating that “We are People, not Machines“.

So, don’t forget to notify humanstxt.org about your participation and let us enjoy your work by appearing in the list of humans.

Anna Ladoshkina is a developer with a primarily statistical and analytical background so she is interested first of all in approaches and techniques that allow her to implement this knowledge in her web projects.

Comments

    • karl,
    • November 7, 2011
    / Reply

    This is actually the first time I’ve heard of humans.txt (as opposed to robots.txt) and I think it is another great innovation to web development. Thanks for sharing!

  1. / Reply

    Great Article;
    we also have the HumansTXT Generator in the following URL:

    http://humanstxt-creator.org

    Hope be useful.
    Best Regards!

  2. / Reply

    It’s really a good idea to add such cute humans.txt to the website to indicate the authorship of developers. I think this data can be lost, but in a such cute and unobtrasive way everyone will notice the authors. Anna, thank you for the informative article.

  3. / Reply

    Thank you for the tutorial, I learned about this a week or two ago, and I never got around to learning how to use it. This sounds like a good way to make sure everyone gets proper credit. :)

    • ghd glattejern,
    • November 8, 2011
    / Reply

    This is actually the first time I’ve heard of humans.txt (as opposed to robots.txt) and I think it is another great innovation to web development. Thanks for sharing!

  4. / Reply

    This post is rather new to me, as I haven’t heard about humans.txt yet. So I’ll study this issue carefully, and try to make mentioned authority in some design sample. Wish me luck :)

    • Till,
    • November 11, 2011
    / Reply

    There is a humans.txt plugin which does exactly all that for you, and more: http://wordpress.org/extend/plugins/humanstxt/

  5. / Reply

    thanks for helping information in this article.

  6. / Reply

    well this is interesting. me too, my first time hearing this. thanks for sharing!

  7. / Reply

    I generated a github repo with this functions and a couple of modifications:
    * humans.txt exist as independient file
    * all functions for generating and reading of humans.txt has moved to it’s own directory

    https://github.com/oldlastman/no-plugins-wp-humanstxt

    thanks for the post

  8. / Reply

    thank you. i will definitely add human.txt to my client’s site after reading your post! thank you for sharing. :)

    • Ben,
    • September 7, 2012
    / Reply

    Ironic that you don’t have a humans.txt on your page.

    1. / Reply

      Hello Ben,

      What do you mean by ‘my’ page? On my own site I have such a page (despite the fact that there is not much sence in it – because all information is on the site whatsoever) – http://www.foralien.com/humans.txt

      If you mean here, in OXP – you have probably noted that this is a guest post, so that there is not and could not be any humans.txt related to me :)

      If you mean my vCard on about.me service – unfortunately, this is a third-party service that simply does not provide such functionality.

      I’d like to assure you that all this code and recomendations were arised from practice, not from a bare coding exercises :) Thank you for your attention to the subject!

Leave a Reply

Your email address will not be published. Required fields are marked *

Deals

Iconfinder Coupon Code and Review

Iconfinder offers over 1.5 million beautiful icons for creative professionals to use in websites, apps, and printed publications. Whatever your project, you’re sure to find an icon or icon…

WP Engine Coupon

Considered by many to be the best managed hosting for WordPress out there, WP Engine offers superior technology and customer support in order to keep your WordPress sites secure…

InMotion Hosting Coupon Code

InMotion Hosting has been a top rated CNET hosting company for over 14 years so you know you’ll be getting good service and won’t be risking your hosting company…

SiteGround Coupon: 60% OFF

SiteGround offers a number of hosting solutions and services for including shared hosting, cloud hosting, dedicated servers, reseller hosting, enterprise hosting, and WordPress and Joomla specific hosting.

d
c