loading...

How To Add Custom Fields to Your Gatsby RSS Feed

harrison_codes profile image Harrison Reid Originally published at daysof.dev on ・3 min read

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.

Posted on by:

harrison_codes profile

Harrison Reid

@harrison_codes

My side projects haunt my dreams.

Discussion

markdown guide