给你的个人网站添加 Newsletter 订阅

1,055 阅读2分钟

“Share your work” 这本书中介绍 email 相对于社交账号和 RSS,会更紧密地和你的用户(粉丝)保持联系,并且曝光率也更高,毕竟每个人都有邮箱。

所以,本文介绍如何使用 Revue 这个服务来给你的个人网站添加 Newsletter 订阅。

Revue

Revue 是一个提供 Newsletter 的服务平台,在 2021 年被 Twitter 公司收购。如果喜欢逛 Twitter 的用户,有时候可能可以看到某个用户主页会展示 Newsletter 订阅,其背后就是 Revue 提供的服务,比如我的主页

除了 Revue 之外,类似的还有其他平台:

创建 Revue 账号

可以直接使用 Twitter 账号注册,注册之后,由于我们需要集成到自己的页面上,因此需要根据其开发的接口来进行定制。接口的地址在:www.getrevue.co/api。

调用接口需要申请。正常的情况下,你应该在 www.getrevue.co/app/integra… 这个页面的底部申请。申请通过后,你会得到如下的一串 api_key:

处理 API KEY

千万不要在开源平台上传敏感数据。在 Next.js 中,为了满足本地测试,可以新建一个 .env.local本地环境变量文件,并将其添加到 .gitignore 文件中。

# .env.local
REVUE_API_KEY=3nahgxxxxxxxxxxxxxxxxxxxx

对于生产环境需要使用 api_key,就需要在部署或运行时添加环境环境变量。比如使用 vercel 进行发布的时候,就可以如下配置:

处理 Revue 请求

接下来,来实现 Newsletter 订阅最重要的请求。根据 Next.js 提供的 API Routes,可以将这个请求封装成一个 api 路由:

// pages/api/subscribe.ts
import type { NextApiRequest, NextApiResponse } from 'next';

export default async function handler(req: NextApiRequest, res: NextApiResponse) {
	const { email } = req.body;
    // 处理本地跨域问题
	res.setHeader('Access-Control-Allow-Origin', '*');

	if (!email) {
		return res.status(400).json({
			error: 'Email is required'
		});
	}
	// https://www.getrevue.co/api#post-/v2/subscribers

	const revRes = await fetch('https://www.getrevue.co/api/v2/subscribers', {
		method: 'POST',
		headers: {
			Authorization: `Token ${process.env.REVUE_API_KEY}`,
			'Content-Type': 'application/json'
		},
		body: JSON.stringify({ email, double_opt_in: false })
	});

	const data = await revRes.json();

	if (!revRes.ok) {
		return res.status(500).json({
			error: data?.error?.email[0]
		});
	}
	return res.status(201).json({ error: '' });
}

实现一个 Subscribe 组件

接下来,使用原生的 form 标签实现一个 Subscrible 组件。具体代码如下:

import React, { FormEvent, useRef, useState } from 'react';

const Subscribe = () => {
  const inputEl = useRef<HTMLInputElement>(null);
  const [errMsg, setErrMsg] = useState('');
  const [loading, setLoading] = useState(false);

  const subscribe = async (e: FormEvent) => {
    e.preventDefault();
    setLoading(true);

    const res = await fetch('/api/subscribe', {
      body: JSON.stringify({
        email: inputEl?.current?.value
      }),
      headers: {
        'Content-Type': 'application/json'
      },
      method: 'POST'
    });

    setLoading(false);
    const json = await res.json();
    const { error } = json;

    if (error) {
      setErrMsg(error);
      return;
    }

    if (inputEl?.current?.value) {
      inputEl.current.value = '';
    }

    setErrMsg('Success! 🎉 You are now subscribed to the newsletter.');
  };

  return (
    <>
      <p>Subscribe to the newsletter</p>
      <p>
        Get emails from me about web development, tech, and early access to new articles. I will
        only send emails when new content is posted. No spam.
      </p>
      <form onSubmit={subscribe}>
        <input
          ref={inputEl}
          placeholder="Your e-mail address"
          type="email"
          autoComplete="email"
          required
        />
        {errMsg && <div>{errMsg}</div>}
        <button
          type="submit"
          {loading ? 'Loading': 'Subscribe'}
        </button>
      </form>
    </>
  );
};

export default Subscribe;

最终获得的效果如下:

更多效果可访问我的个人网站 www.nazha.co/. 在这里,你可以找到源码