├── .babelrc
├── .editorconfig
├── .eslintignore
├── .eslintrc
├── .gitignore
├── .npmignore
├── .prettierrc
├── HISTORY.md
├── LICENSE
├── README.md
├── __tests__
└── gatsby-node.test.js
├── examples
├── .gitignore
├── .prettierrc
├── README.md
├── gatsby-config.js
├── package.json
└── src
│ ├── components
│ ├── header.js
│ ├── layout.css
│ └── layout.js
│ ├── images
│ └── gatsby-icon.png
│ └── pages
│ └── index.js
├── gatsby-node.js
├── img
├── mailchimp_form_action.png
├── mailchimp_list.png
├── mailchimp_list_fields.png
└── mc_groups.png
├── index.js
├── jest.config.js
├── package.json
├── src
├── gatsby-node.js
└── index.js
└── yarn.lock
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": ["@babel/preset-env"]
3 | }
4 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | # Editorconfig: https://editorconfig.org/
2 |
3 | root = true
4 |
5 | [*]
6 | charset = utf-8
7 | indent_style = tab
8 | end_of_line = lf
9 | insert_final_newline = true
10 | trim_trailing_whitespace = true
11 | indent_style = space
12 | indent_size = 4
13 |
--------------------------------------------------------------------------------
/.eslintignore:
--------------------------------------------------------------------------------
1 | /index.js
2 | /gatsby-node.js
--------------------------------------------------------------------------------
/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "env": {
3 | "browser": true,
4 | "node": true,
5 | "es6": true,
6 | "jest": true
7 | },
8 | "extends": ["airbnb-base", "plugin:react/recommended", "prettier"],
9 | "globals": {
10 | "Atomics": "readonly",
11 | "SharedArrayBuffer": "readonly"
12 | },
13 | "parser": "babel-eslint",
14 | "parserOptions": {
15 | "ecmaFeatures": {
16 | "jsx": true
17 | },
18 | "ecmaVersion": 2018,
19 | "sourceType": "module"
20 | },
21 | "plugins": ["react", "prettier"],
22 | "rules": {
23 | "prettier/prettier": "error",
24 | "no-unused-vars": [
25 | "error",
26 | {
27 | "vars": "local",
28 | "args": "none"
29 | }
30 | ],
31 | "no-plusplus": "off",
32 | "no-underscore-dangle": "off",
33 | "no-restricted-syntax": ["off", "BinaryExpression[operator='in']"]
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | .DS_Store
3 | yarn-error.log
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 |
5 | # Runtime data
6 | pids
7 | *.pid
8 | *.seed
9 |
10 | # Directory for instrumented libs generated by jscoverage/JSCover
11 | lib-cov
12 |
13 | # Coverage directory used by tools like istanbul
14 | coverage
15 |
16 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
17 | .grunt
18 |
19 | # node-waf configuration
20 | .lock-wscript
21 |
22 | # Compiled binary addons (http://nodejs.org/api/addons.html)
23 | build/Release
24 |
25 | # Other
26 | *.un~
27 | .babelrc
28 | .gitignore
29 | .npmignore
30 | CHANGELOG.md
31 | LICENSE
32 | README.md
33 | coverage
34 | decls
35 | examples
36 | flow-typed
37 | node_modules
38 | src
39 | yarn.lock
--------------------------------------------------------------------------------
/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "printWidth": 100,
3 | "tabWidth": 4,
4 | "useTabs": false,
5 | "semi": true,
6 | "singleQuote": true,
7 | "trailingComma": "all",
8 | "bracketSpacing": true,
9 | "jsxBracketSameLine": false,
10 | "proseWrap": "always"
11 | }
12 |
--------------------------------------------------------------------------------
/HISTORY.md:
--------------------------------------------------------------------------------
1 | ## Version History
2 |
3 | **5.2.0**
4 |
5 | - Make timeout configurable (#68)
6 |
7 | **5.1.0**
8 |
9 | - Adds ability to override default Mailchimp endpoint with a custom one
10 |
11 | **5.0.1**
12 |
13 | - Adds eslint and prettier
14 |
15 | **5.0.0**
16 |
17 | - Adds support for Mailchimp Groups. See README.md for more details on how to implement.
18 |
19 | **4.0.0**
20 |
21 | - Gatsby v2 is now default. See README.md for upgrade details.
22 |
23 | **3.0.0**
24 |
25 | - uses `gatsby-node` and [Webpack DefinePlugin](https://webpack.js.org/plugins/define-plugin/) to
26 | extract your Mailchimp API key during _compile time only_, set it to global, then use it to make
27 | the http request. Previously, we were importing your entire `gatsby-config` file
28 |
29 | **2.0.0**
30 |
31 | - return a promise, not string, from an error'd http request
32 |
33 | ## To do
34 |
35 | - ensure MC endpoint is valid
36 | - create basic MC field form (name, email, submit button)
37 | - spec
38 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 Benjamin Hoffman
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## 😞 No longer actively maintained 😞
2 | _My sincerest apologies but this repo is no longer maintained. You can still use it and most people have reported that it works great, but I am no longer adding features or fixing bugs. Please use at your own risk and keep in mind it likely won't handle corner cases or your specific use case (it's hopefully fine for generic use cases)._ -- Ben (Dec 21, 2021)
3 |
4 | ## 🗣 Actively looking for repo maintainers! 📣
5 | I no longer have time to manage this package and would love if someone could help me maintain it. Please open an issue if you're interested and we'll chat! 🙏🏽
6 |
7 | ---
8 |
9 | # Subscribe emails to your Mailchimp list
10 |
11 | This Gatsby plugin helps you subscribe new email addresses to a Mailchimp email list. Mailchimp does
12 | not provide much direction on making clientside requests so the setup to achieve this with a static
13 | website (i.e. Gatsby) can be cumbersome.
14 |
15 | ## We need your help! 🙏🏽
16 | We're looking for active contributors to this repo! If you're interested, simply open an issue or PR of your own and indicate that you'd like to help. Check out our open issues and PRs. We also need to beef up testing. Contributors get to:
17 | - manage versioning and deploys by publishing new versions to NPM
18 | - determine which features get launched by merging pull requests
19 | - oversee the community through commenting on and managing pull requests and issues
20 |
21 | ⚜️ Being an active contributor is great for the community and your engineering resume.⚜️
22 |
23 | ## How It Works Under The Hood
24 |
25 | First we scan your `gatsby-config` for your MC endpoint. Then, once you import and invoke the
26 | `addToMailchimp` method in your React component, it makes a jsonp request to your endpoint with the
27 | email, attributes, and any group fields you include in the request.
28 |
29 | ## Getting Started
30 |
31 | There are three steps involved to getting started:
32 |
33 | 1. add this plugin to your repo
34 |
35 | - In the root directory of your Gatsby project, run the following command in your terminal:
36 |
37 | ```
38 | # npm
39 | $ npm install gatsby-plugin-mailchimp
40 |
41 | # yarn
42 | $ yarn add gatsby-plugin-mailchimp
43 | ```
44 |
45 | 2. add your Mailchimp endpoint to your `gatsby-config.js` file (see below for instructions)
46 | 3. import & invoke the `addToMailchimp` method exported by this plugin
47 |
48 | ## Using Gatsby v1?
49 |
50 | If you are still on Gatsby v1.x, you need to use an old version of this plugin. There were a lot of
51 | changes made in Gatsby v2 that will cause this plugin to break so make sure to use the correct
52 | version of this plugin if you are still on Gatsby v1.
53 |
54 | We no longer maintain this version.
55 |
56 | Simply update your `package.json` to:
57 |
58 | ```
59 | # npm
60 | $ npm install https://github.com/benjaminhoffman/gatsby-plugin-mailchimp.git#gatsby-v1
61 |
62 | # yarn
63 | $ yarn add https://github.com/benjaminhoffman/gatsby-plugin-mailchimp.git#gatsby-v1
64 | ```
65 |
66 | ## Gatsby Config Instructions
67 |
68 | You need to provide this plugin with your Mailchimp account and list details in order for it to know
69 | which endpoint to save the email address to. Follow these directions:
70 |
71 | In your `gatsby-config.js` file, add the following code to the plugin section:
72 |
73 | ```javascript
74 | plugins: [
75 | ...{
76 | resolve: 'gatsby-plugin-mailchimp',
77 | options: {
78 | endpoint: '', // string; add your MC list endpoint here; see instructions below
79 | timeout: 3500, // number; the amount of time, in milliseconds, that you want to allow mailchimp to respond to your request before timing out. defaults to 3500
80 | },
81 | },
82 | ];
83 | ```
84 |
85 | ### Mailchimp Endpoint
86 |
87 | Your Mailchimp endpoint will look something like this:
88 | _https://example.us10.list-manage.com/subscribe/post?u=b9ef2fdd3edofhec04ba9b930&id=3l948gkt1d_
89 |
90 | Here is how you can locate your Mailchimp endpoint.
91 |
92 | 1. Login to your Mailchimp account
93 | 2. Click "Lists" tab at the top
94 | 3. Locate the Mailchimp list you want to save email addresses to
95 | 4. Click that list
96 | 5. Click the subtab "Signup forms"
97 | 6. Click "Embedded forms"
98 |
99 | 
100 |
101 | 7. Scroll down to the section with all the HTML code
102 | 8. Locate the HTML form element. Copy the entire URL listed under the form "action" attribute\*
103 | 9. Paste that URL into your `gatsby-config`ʼs `option.endpoint` field
104 |
105 | 
106 |
107 | ... that's all!
108 |
109 | ## Gatsby Import Plugin Instructions
110 |
111 | This plugin exports one method -- `addToMailchimp` -- that accepts one required argument (`email`)
112 | and two optional fields (`fields` and `endpointOverride`).
113 |
114 | - `email` is a valid email string
115 | - `fields` is an object of attributes youʼd like to save with the email address. More detailed
116 | instructions below.
117 | - `endpointOverride` is if you want to pass in a custom MC endpoint (one that is different than
118 | the one listed in your config file. See below for details)
119 |
120 | Navigate to the file where you collect email addresses (ie, the file you want to import this plugin
121 | into). When a user submits a form and includes at least their email address, invoke the
122 | `addToMailchimp` method like you would any other method. Here is an example:
123 |
124 | ```javascript
125 | import addToMailchimp from 'gatsby-plugin-mailchimp'
126 | ...
127 |
128 | export default class MyGatsbyComponent extends React.Component {
129 | // Since `addToMailchimp` returns a promise, you
130 | // can handle the response in two different ways:
131 |
132 | // Note that you need to send an email & optionally, listFields
133 | // these values can be pulled from React state, form fields,
134 | // or wherever. (Personally, I recommend storing in state).
135 |
136 | // 1. via `.then`
137 | _handleSubmit = e => {
138 | e.preventDefault();
139 | addToMailchimp(email, listFields) // listFields are optional if you are only capturing the email address.
140 | .then(data => {
141 | // I recommend setting data to React state
142 | // but you can do whatever you want (including ignoring this `then()` altogether)
143 | console.log(data)
144 | })
145 | .catch(() => {
146 | // unnecessary because Mailchimp only ever
147 | // returns a 200 status code
148 | // see below for how to handle errors
149 | })
150 | }
151 |
152 | // 2. via `async/await`
153 | _handleSubmit = async (e) => {
154 | e.preventDefault();
155 | const result = await addToMailchimp(email, listFields)
156 | // I recommend setting `result` to React state
157 | // but you can do whatever you want
158 | }
159 |
160 | render () {
161 | return (
162 |
165 | )
166 | }
167 | }
168 | ```
169 |
170 | ## Returns
171 |
172 | This plugin returns a promise that resolves to the object that is returned by Mailchimpʼs API. The
173 | Mailchimp API will always return a status of 200. In order to know if your submission was a success
174 | or error, you must read the returned object, which has a `result` and `msg` property:
175 |
176 | ```javascript
177 | {
178 | result: string; // either `success` or `error` (helpful to use this key to update your state)
179 | msg: string; // a user-friendly message indicating details of your submissions (usually something like "thanks for subscribing!" or "this email has already been added")
180 | }
181 | ```
182 |
183 | ## Mailchimp List Fields
184 |
185 | Sometimes you want to send to Mailchimp more than just an email address. Itʼs very common to also
186 | send a first name, last name, pathname, etc. Honestly, you can send whatever you want to store
187 | alongside the email address. Instructions below on how to create new list fields but once youʼve set
188 | them up in Mailchimp, you send them alongside the email like this:
189 |
190 | ```javascript
191 | addToMailchimp('email@example.com', {
192 | PATHNAME: '/blog-post-1',
193 | FNAME: 'Ben',
194 | LNAME: 'Coder'
195 | ...
196 | })
197 | ```
198 |
199 | ## Mailchimp Groups
200 |
201 | Mailchimp offers the concept of list groups. It's a bit tricky to implement here because you _must_
202 | use the exact key and value as defined in your MC Embedded Form for those fields.
203 |
204 | To add these you must go back to your "Embedded Forms" (where you got your endpoint from) and find
205 | the form field that represents the group you want to add this user to. Next, copy the name and use
206 | that as your key in the `addToMailchimp` field param. The name field will have weird values like
207 | `group[21265][2]` or `group[21269]`.
208 |
209 | Similarly, the `input` field `value` must also be the same as you see. This means you must either
210 | set the name and value fields manually in your form or keep a mapping in your JS file.
211 |
212 | Why do we need to use these weird structure for name and value field? Because this is what Mailchimp
213 | expects. 🤷🏽♂️
214 |
215 | For example, here is a screenshot of what this looks like:
216 |
217 | 
218 |
219 | And the code would be:
220 |
221 | ```
222 | # HTML
223 | /*
224 | Here we chose to name the input field the same as what's in
225 | our embedded form. But you can name it whatever you want and keep
226 | a field name map in your JS. Mailchimp expects the name and value
227 | to match what's in its Embedded Form
228 | */
229 |
230 |
231 | # JS
232 | addToMailchimp('email@example.com', {
233 | PATHNAME: '/blog-post-1',
234 | FNAME: 'Ben',
235 | LNAME: 'Coder',
236 | 'group[21265][2]': '2',
237 | ...
238 | })
239 | ```
240 |
241 | See here for [thread](https://github.com/benjaminhoffman/gatsby-plugin-mailchimp/pull/31).
242 |
243 | ## Multiple Mailchimp lists
244 |
245 | Many people asked for the ability to send users to different Mailchimp lists. We added that
246 | capability! How we added this capability without a breaking change is by allowing you to _override_
247 | the endpoint that's listed in your `gatsby-config.js` file. When you invoke `addToMailchimp`, pass
248 | in a third argument of the list you'd like to subscribe this email address to. That will override
249 | the default one listed in your config.
250 |
251 | ```javascript
252 | addToMailchimp(
253 | 'ben@gatsby-plugin-mailchimp.com',
254 | {
255 | /* list fields here*/
256 | },
257 | 'https://example.us10.list-manage.com/subscribe/post?u=b9ef2fdd3ed',
258 | );
259 | ```
260 |
261 | ## Example
262 |
263 | See directory in this repo called `/examples`.
264 |
265 | ## Gotchas
266 |
267 | 1. _email address_: pass in the email as normal (ie, `you@gmail.com`). Do _not_ encode or transform
268 | the email, as our plugin will do that for you!
269 |
270 | 2. _listFields_: many times you want to collect more than just an email address (first/last name,
271 | birthday, page pathname). I like to store this info in React state and pass it in as list fields.
272 | See below.
273 |
274 | 3. I like to save the returned data to React state so I can then display a success/error message to
275 | the user.
276 |
277 | 4. There is a
278 | [current known issue (#15)](https://github.com/benjaminhoffman/gatsby-plugin-mailchimp/issues/15)
279 | where this plugin does _not work_ if the Mailchimp List has
280 | [reCAPTCHA enabled](https://mailchimp.com/help/about-recaptcha-for-signup-forms/#Enable-reCAPTCHA/).
281 | This setting should be turned off for everything to function properly.
282 |
283 | ### Create, Remove, or Edit Mailchimp List Fields
284 |
285 | To setup or modify Mailchimp list fields, navigate to your MC list, click "Settings", then click
286 | "List fields". Then add, remove, or edit fields as you wish. Make sure to update your
287 | `addToMailchimp` listFields object after youʼve made changes in Mailchimp.
288 |
289 | 
290 |
291 | ## Contributing
292 |
293 | If you'd like to contribute, simply open a PR or open an issue!
294 |
--------------------------------------------------------------------------------
/__tests__/gatsby-node.test.js:
--------------------------------------------------------------------------------
1 | const { onCreateWebpackConfig } = require('../gatsby-node');
2 |
3 | describe('gatsby-node > onCreateWebpackConfig', () => {
4 | const plugins = {};
5 | const actions = {};
6 |
7 | beforeEach(() => {
8 | plugins.define = jest.fn();
9 | actions.setWebpackConfig = jest.fn();
10 | });
11 |
12 | it('Throws an error when endpoint is not a string', () => {
13 | const endpoint = 123;
14 | expect(() => onCreateWebpackConfig({ plugins, actions }, { endpoint })).toThrow(Error);
15 | expect(actions.setWebpackConfig).not.toHaveBeenCalled();
16 | expect(plugins.define).not.toHaveBeenCalled();
17 | });
18 |
19 | it('Throws an error when endpoint is length is lesser than 40 chars', () => {
20 | const endpoint = 'https://my-endpoint';
21 | expect(() => onCreateWebpackConfig({ plugins, actions }, { endpoint })).toThrow(Error);
22 | expect(actions.setWebpackConfig).not.toHaveBeenCalled();
23 | expect(plugins.define).not.toHaveBeenCalled();
24 | });
25 |
26 | describe('Options -> calls set setWebpackConfig and define variables correctly', () => {
27 | it('with default values', () => {
28 | const endpoint = `https://my-endpoint-with-more-than-40-chars.com`;
29 |
30 | expect(actions.setWebpackConfig).not.toHaveBeenCalled();
31 | expect(plugins.define).not.toHaveBeenCalled();
32 |
33 | onCreateWebpackConfig({ plugins, actions }, { endpoint });
34 |
35 | expect(actions.setWebpackConfig).toHaveBeenCalledTimes(1);
36 | expect(plugins.define).toHaveBeenCalledTimes(1);
37 | expect(plugins.define).toHaveBeenCalledWith(
38 | expect.objectContaining({
39 | __GATSBY_PLUGIN_MAILCHIMP_ADDRESS__: expect.any(String),
40 | __GATSBY_PLUGIN_MAILCHIMP_TIMEOUT__: 3500,
41 | }),
42 | );
43 | });
44 |
45 | it('with timeout value', () => {
46 | const endpoint = `https://my-endpoint-with-more-than-40-chars.com`;
47 | const timeout = 10000;
48 |
49 | expect(actions.setWebpackConfig).not.toHaveBeenCalled();
50 | expect(plugins.define).not.toHaveBeenCalled();
51 |
52 | onCreateWebpackConfig({ plugins, actions }, { endpoint, timeout });
53 |
54 | expect(actions.setWebpackConfig).toHaveBeenCalledTimes(1);
55 | expect(plugins.define).toHaveBeenCalledTimes(1);
56 | expect(plugins.define).toHaveBeenCalledWith(
57 | expect.objectContaining({
58 | __GATSBY_PLUGIN_MAILCHIMP_ADDRESS__: expect.any(String),
59 | __GATSBY_PLUGIN_MAILCHIMP_TIMEOUT__: timeout,
60 | }),
61 | );
62 | });
63 | });
64 | });
65 |
--------------------------------------------------------------------------------
/examples/.gitignore:
--------------------------------------------------------------------------------
1 | # Project dependencies
2 | .cache
3 | node_modules
4 | yarn-error.log
5 |
6 | # don't need this; allow for user to fresh install packages
7 | yarn.lock
8 |
9 | # Build directory
10 | /public
11 | .DS_Store
12 |
--------------------------------------------------------------------------------
/examples/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "semi": false,
3 | "singleQuote": true,
4 | "trailingComma": "es5"
5 | }
6 |
--------------------------------------------------------------------------------
/examples/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | ## Example of `gatsby-plugin-mailchimp` for Gatsby v2.
6 |
7 |
8 | This example repo combines `gatsby-starter-default` with `gatsby-plugin-mailchimp` for Gatsby **v2**. It's nothing special -- I didn't change anything. It's mostly used for you to see how to use this plugin.
9 |
10 | See something missing from this example? Let me know and I will update it! ... or even better, open your own PR and I'll merge it!
11 |
12 | You can follow the instructions below and submit the form to see the results.
13 |
14 | ## Steps
15 | 1. clone down this repo
16 | 2. add your mailchimp endpoint to `gatsby-config`
17 | 3. `$ yarn install`
18 | 4. `$ yarn develop`
19 | 5. go to `localhost:8000/` in your browser and open your the console
20 | 6. submit a form. see the page & form state get logged to the screen
21 |
--------------------------------------------------------------------------------
/examples/gatsby-config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | siteMetadata: {
3 | title: 'Gatsby Default Starter',
4 | },
5 | plugins: [
6 | 'gatsby-plugin-react-helmet',
7 | {
8 | resolve: 'gatsby-plugin-mailchimp',
9 | options: {
10 | endpoint: '', // replace with your own Mailchimp endpoint for testing
11 | },
12 | },
13 | ],
14 | }
15 |
--------------------------------------------------------------------------------
/examples/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "gatsby-starter-default",
3 | "description": "Gatsby default starter",
4 | "version": "1.0.0",
5 | "author": "Kyle Mathews ",
6 | "dependencies": {
7 | "gatsby": "next",
8 | "gatsby-plugin-mailchimp": "^5.1.2",
9 | "gatsby-plugin-react-helmet": "^3.0.7",
10 | "react": "^16.4.2",
11 | "react-dom": "^16.4.2",
12 | "react-helmet": "^5.2.0"
13 | },
14 | "keywords": [
15 | "gatsby"
16 | ],
17 | "license": "MIT",
18 | "scripts": {
19 | "build": "gatsby build",
20 | "develop": "gatsby develop",
21 | "serve": "gatsby serve",
22 | "format": "prettier --write '**/*.js'",
23 | "test": "echo \"Error: no test specified\" && exit 1"
24 | },
25 | "devDependencies": {
26 | "prettier": "^1.14.2"
27 | },
28 | "repository": {
29 | "type": "git",
30 | "url": "https://github.com/gatsbyjs/gatsby-starter-default"
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/examples/src/components/header.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { Link } from 'gatsby'
3 |
4 | const Header = () => (
5 |
11 |
18 |
19 |
26 | Example usage of gatsby-plugin-mailchimp
27 |
28 |