How To Add Custom Fields to Your Gatsby RSS Feed

harrison_codes

Harrison Reid

Posted on July 6, 2020

How To Add Custom Fields to Your Gatsby RSS Feed

I've recently launched a product I've been working on for while: Ippy.io - a better resume builder. It's live on Product Hunt now, so check it out here if you're interested šŸ˜€


What youā€™ll learn:

  • How to declare custom namespaces on your Gatsby RSS feed
  • How to use the namespaces to add custom elements

What youā€™ll build:

  • An RSS feed with custom data!

Iā€™ve recently been working on adding up an RSS feed for Days of Dev using gatsby-plugin-feed.

While setting this up, I found myself facing a small roadblock; I wanted to add additional custom data to the RSS feed, and couldnā€™t figure out how to get it working. Specifically, I wanted to add the full text of tweets that Iā€™d auto generate from various frontmatter fields.

This would allow me to easily post to my social accounts through Zapier without having to mess around with any complex logic to compose the tweets in Zapier itself (and importantly, let me avoid having to pay for a premium account!).

It wasnā€™t immediately clear to me from the Gatsby docs how to get this working, so I thought Iā€™d post this up here in case anyone faces the same problem in the futture!

Itā€™s worth noting it is actually documented, but itā€™s included under a header explaining how to add iTunes RSS blocks, which I didnā€™t pick up on initially.

The Key: Namespaces

If you, like me, know next to nothing about RSS, you mightā€™ve assumed that you can just throw any XML into an RSS feed. Well, actually, you pretty much can! But there is a slight catchā€¦

To add custom elements (with custom data), you need to namespace them.

Fortunately, this is reasonably straightforward (particularly because weā€™re using gatsby-plugin-feed). Basically, it means that in the output XML, you need to declare the namespace, then prefix all of your custom xml tags with the declared namespace.

For example, in the RSS feed for Days of Dev (available at daysof.dev/rss.xml), youā€™ll see the namespace declaration in the opening <rss> tag - xmlns:daysofdev="https://www.daysof.dev".

Then, when Iā€™ve added custom data, the tag name is always prefixed with the namespace followed by a colon. For example, the tag containing the tweet for a given post is included as: <daysofdev:tweet>Some text...</daysofdev:tweet>

Setting up gatsby-plugin-feed

Using gatsby-plugin-feed to set up namespaces, and include custom data, is relatively straightforward.

To start with, follow the instructions in the gatsby docs to customise the RSS feed plugin.

This should leave you with a gatsby-config.js with a plugin config for gatsby-plugin-feed that looks something like the following. Note that Iā€™ve excluded a number of the option fields here for brevity, so directly copy-pasting the whole snippet will almost certainly cause you problems.

module.exports = {
  plugins: [
    {
      resolve: `gatsby-plugin-feed`,
      options: {
        feeds: [
          {
            serialize: ({
              query: { allMarkdownRemark },
            }) => {
              return allMarkdownRemark.edges.map((edge) => {
                return Object.assign(
                  {},
                  edge.node.frontmatter,
                  {
                    ...
                    custom_elements: [
                      { "content:encoded": edge.node.html },
                    ],
                  }
                );
              });
            },
            ...
          },
        ],
      },
    },
  ],
};

To include a custom element, we need to make two changes:

Firstly, we need to tell gatsby-plugin-feed about the namespace we wish to declare. This is achieved by adding the setup option, which extends the options with a custom_namespaces field. In this example, weā€™ve added yournamespace. I donā€™t think the URL value of the is particularly important, as long as itā€™s unique to your namespace.

Secondly, we include the custom element under the custom_elements field in the output of the serialize function. You can see this added in the example as:

{ "yournamespace:yourcustomfield": edge.node.fields.someField }

Note that the custom element name must use the namespace, followed by a colon.

module.exports = {
  plugins: [
    {
      resolve: `gatsby-plugin-feed`,
      options: {
        setup: (options) => ({ ...options, custom_namespaces: { yournamespace: "https://www.yournamespace.com", }, }), feeds: [
          {
            serialize: ({
              query: { allMarkdownRemark },
            }) => {
              return allMarkdownRemark.edges.map((edge) => {
                return Object.assign(
                  {},
                  edge.node.frontmatter,
                  {
                    ...
                    custom_elements: [
                      { "content:encoded": edge.node.html },
                      { "yournamespace:yourcustomfield": edge.node.fields.someField } ],
                  }
                );
              });
            },
          },
        ],
        ...
      },
    },
  ],
};

This should be all you need to add arbitrary custom data to your RSS feed generated by gatsby-plugin-feed. When you next deploy your app, you should have the custom data available to make use of wherever your RSS feed is being consumed.

šŸ’– šŸ’Ŗ šŸ™… šŸš©
harrison_codes
Harrison Reid

Posted on July 6, 2020

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related