crazymatt
crazymatt

Reputation: 3286

Modifing RSS nodes in WordPress

I have been asked by my work to add a rel='nofollow' to the WordPress RSS feed on our site. Now the RSS feed already has the rel='nofollow' added to all the <a href> tags which is working fine. What they are really asking is to add the nofollow to the actual RSS node itself.

They basically want <link rel='nofollow'> instead of <link>

Would adding a nofollow at the node level actually do anything? I understand it working at the href level but it seems odd to do this here. If this does work as expected then using PHP how can I modify this node to add this namespace?

Here is an example of my RSS feed.

<?xml version="1.0" encoding="UTF-8"?>
    <rss version="2.0"
        xmlns:content="http://purl.org/rss/1.0/modules/content/"
        xmlns:wfw="http://wellformedweb.org/CommentAPI/"
        xmlns:dc="http://purl.org/dc/elements/1.1/"
        xmlns:atom="http://www.w3.org/2005/Atom"
        xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
        xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
    >

<channel>
    <title>Article Title here</title>
    <link>http://fakewebsiteurl.com</link>
    <description>article description here</description>
    <language>en-US</language>
    <generator>https://wordpress.org/?v=4.5.2</generator>
    <item>
        <title>Test Article</title>
        <link>http://fakewebsiteurl.com/news/test-article/</link>
        <comments>http://fakewebsiteurl.com/news/test-article/#respond</comments>
        <pubDate>Thu, 05 May 2016 18:16:50 +0000</pubDate>

        <description><![CDATA[<p>Description text here</p>
<p>The post <a rel="nofollow" href="fakewebsiteurl.com/news/test-article/">Test Article</a> appeared here</p>
]]></description>
    </item>
    <item>
        ...
    </item>
</channel>

I have a custom PHP page that modifies this RSS already but I am not sure if I need to replace the node completely or if there is a away to modify it directly. I was thinking of using str_replace but that did not work.

<?php

namespace X;

class RssFeed {

    public function __construct() {
        add_filter( 'the_content_feed', array( $this, 'add_nofollow_href' ) );
    }

    function add_nofollow_namespace($content) {
        if (is_feed()) {
            $link = '<link>';
            $linkno = '<link rel="nofollow">';
            $updated = str_replace($link, $linkno, $content);
            return $updated;
        }
    }
}
?>

Thanks in advance. Code examples appreciated.

Upvotes: 4

Views: 864

Answers (2)

birgire
birgire

Reputation: 11378

I tested the W3C Feed Validator with the rel="nofollow" attribute on the <link> tag:

This feed does not validate. line 13, column 1: Unexpected rel attribute on link element [help] <link rel="nofollow">http://exapmle.tld</link>

so the modified feed would not validate:

The nofollow keyword may be used with a and area elements. This keyword does not create a hyperlink, but annotates any other hyperlinks created by the element (the implied hyperlink, if no other keywords create one).

The nofollow keyword indicates that the link is not endorsed by the original author or publisher of the page, or that the link to the referenced document was included primarily because of a commercial relationship between people affiliated with the two pages.

The <link> tag is required by the rss2 specification, so removing (via plugin or custom template) wouldn't be an option. A drastic approach would be to disable the whole feed altogether (e.g. mentioned here).

It's possible to add a custom namsespace via the rss2_ns hook and custom channel nodes via the rss2_head hook. The atom namespace is already included for the self relationship of:

<atom:link href="<?php self_link(); ?>" rel="self" type="application/rss+xml" />

Out of curiosity I tested:

<atom:link href="<?php bloginfo_rss('url'); ?>" 
           rel="nofollow" type="application/rss+xml" />

This gave a valid feed, but with warnings regarding nofollow as an unregistered link relationship. But I'm not sure if the search bots would consider this kind of approach?

Previous answer:

Appart from creating a custom feed template (as mentioned by @mevius), the only workaround I can think of is the following output buffering hack through the rss_tag_pre and rss2_head hooks:

add_action( 'rss_tag_pre', function( $tag )
{
    if( 'rss2' === $tag )
        ob_start();
} );

add_action( 'rss2_head', function()
{       
    echo str_replace( '<link>', '<link rel="nofollow">',  ob_get_clean() );
} );

where we target the rss2 feed template.

If you think it's worth to have such an attribute, then you can always create a ticket for it.

Upvotes: 1

rnevius
rnevius

Reputation: 27092

Unfortunately, the only way to reliably do this will be to create a custom feed template. As you can see from the source, the <link> in the core feed templates is hard-coded as the following:

<link><?php bloginfo_rss('url') ?></link>

There is no way to edit attributes of this tag via a filter.

Upvotes: 1

Related Questions