How to Create your first GatsbyJS Plugin
Tags: javascript, gatsby, npm
Published: 2019-10-15 12:23:42

[**This article has been previously been published on my main blog**](https://blog.daudr.me/create-gatsby-plugin)

[**Questo articolo è stato pubblicato precedentemente nel mio blog principale**](https://blog.daudr.me/it/create-gatsby-plugin)

In the [latest article](https://blog.daudr.me/future-of-web-moentizetion), I introduced the new (proposed) web standard per **Web Monetization**. In this new article, we'll see how we can create a simple **GatsbyJS Plugin** to inject the **Web Monetization Meta Tag** using the **SSR APIs**.

![Add a piece to the puzzle](https://images.unsplash.com/photo-1494059980473-813e73ee784b?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1049&q=80)

> Photo by [Hans-Peter Gauster](https://unsplash.com/@sloppyperfectionist) on [Unsplash](https://unsplash.com)

## Create the plugin files

We can read from the [official plugins docs](https://www.gatsbyjs.org/docs/creating-plugins/) that a plugin project has to comprehend some files:

- `package.json` - **required** this can be an empty object (`{}`) for local plugins.
  Also, your `package.json` file should have the following properties:
  - `name` is used to identify the plugin when it mutates Gatsby’s GraphQL data structure  
    if `name` isn’t set, the folder name for the plugin is used
  - `main` is the [name of the file that will be loaded when your module is required by another application](https://docs.npmjs.com/creating-node-js-modules#create-the-file-that-will-be-loaded-when-your-module-is-required-by-another-application)  
    if `main` isn’t set, a default name of `index.js` will be used  
    if `main` isn’t set, it is recommended to create an empty index.js file with the contents `//no-op` (short for no-operation), as seen in [this example plugin](https://github.com/gatsbyjs/gatsby/tree/817a6c14543c73ea8f56c9f93d401b03adb44e9d/packages/gatsby-source-wikipedia)
  - `version` is used to manage the cache — if it changes, the cache is cleared  
    if `version` isn’t set, an MD5 hash of the `gatsby-*` file contents is used to invalidate the cache  
    omitting the `version` field is recommended for local plugins
  - `keywords` is used to make your plugin discoverable  
    plugins published on the npm registry should have `gatsby` and `gatsby-plugin` in the keywords field to be added to the [Plugin Library](https://www.gatsbyjs.org/packages/)
- `gatsby-browser.js` — usage details are in the [`browser API reference`](https://www.gatsbyjs.org/docs/browser-apis/)
- `gatsby-node.js` — usage details are in the [`Node API reference`](https://www.gatsbyjs.org/docs/node-apis/)
- `gatsby-ssr.js` — usage details are in the [`SSR API reference`](https://www.gatsbyjs.org/docs/ssr-apis/)

For the sake of this plugin, we'll use only the SSR APIs, therefore, the only file we need to have is the `gatsby-ssr.js`' one.

## Using SSR APIs

As already said we'll create a plugin that'll need only the SSR APIs, GatsbyJS expose these APIs:

- [`onPreRenderHTML`](https://www.gatsbyjs.org/docs/ssr-apis/#onPreRenderHTML)
- [`onRenderBody`](https://www.gatsbyjs.org/docs/ssr-apis/#onRenderBody)
- [`replaceRenderer`](https://www.gatsbyjs.org/docs/ssr-apis/#replaceRenderer)
- [`wrapPageElement`](https://www.gatsbyjs.org/docs/ssr-apis/#wrapPageElement)
- [`wrapRootElement`](https://www.gatsbyjs.org/docs/ssr-apis/#wrapRootElement)

In our plugin, we'll use only the `onPreRenderHTML` in order to add the **Web Monetization Meta Tag** in the `<head>` section of our pages.
This API gives us an Object containing two methods and a string that we can use to do what we need:

- `getHeadComponents` - return the `headComponents` array, formed by `ReactNode` objects
- `replaceHeadComponents` - Takes an array of components as its first argument which replaces the headComponents array which is passed to the `html.js` component.
- `pathname` - Is the current path that's being generated by Gatsby SSR APIs

You can read more on these in [the official docs](https://www.gatsbyjs.org/docs/ssr-apis/).

## Create our SSR file

At the end our `gatsby-ssr.js` should look like this:

```javascript
const React = require("react");

export const onPreRenderHTML = (
  { reporter, getHeadComponents, replaceHeadComponents, pathname },
  pluginOptions
) => {
  if (process.env.NODE_ENV !== `production`) {
    reporter.warn("non production environment");
    return null;
  }

  if (!pluginOptions.paymentPointer) {
    reporter.warn(
      `Payment Pointer is not defined, add it to your gatsby-config.js file.`
    );
    return null;
  }

  if (pluginOptions.excludedPaths && pluginOptions.excludedPaths.length > 0) {
    const excludedPaths = pluginOptions.excludedPaths;
    let isExcluded = excludedPaths.filter(path => pathname.match(path)).length > 0;
  
    if (isExcluded) {
      return null;
    }
  }

  const headComponents = getHeadComponents();

  const webMonetizationTag = (
    <meta name="monetization" content={pluginOptions.paymentPointer} />
  );

  headComponents.push(webMonetizationTag);

  replaceHeadComponents(headComponents);
};
```

This plugin adds the **Web Monetization Meta Tag** only when it's run on `peoduction` environment (when we use `gatsby build`, for example) and accepts an array of strings (`excludedPaths`), in its configuration, which tells which paths should not have the meta tag.

## Use the plugin in your Gatsby Site

In order to use your new plugin you have to install it through `npm` first:

```bash
npm i gatsby-plugin-web-monetization
```

And then you have to add it in your `gatsby-config.js` file like you already do for all the other plugins.
This plugin in particular can be instantiated like this:

```javascript
module.exports = {
  // Other content ...
  plugins: [
    // Other plugins ...
    {
      resolve: `gatsby-plugin-web-monetization`,
      options: {
        paymentPointer: `YOUR_ILP_PAYMENT_POINTER`,
        excludedPaths: ['exclude', 'path'] // Optional
      }
    }
  ]
};
```

## Publish your new plugin on NPM

In order to publish your new plugin on NPM and make it discoverable by its users, you should first add the fields said above in your `package.json` file and then you can run `npm publish` from the root of your project to publish your new plugin to NPM register. (You have to be logged in to NPM of course 😉)

## That's all 😎😎😎

Congratulations! You've created and published your first GatsbyJS plugin.

The plugin can also be found on [my GitHub](https://github.com/Daudr/gatsby-plugin-web-monetization), leave a ⭐ if you find it useful! 😻