From 2f7d8dfd59b4b10f475b5fd5f1b661e820b4596c Mon Sep 17 00:00:00 2001 From: Anand Chowdhary Date: Wed, 18 Oct 2023 14:11:17 +0200 Subject: [PATCH] ci: Add static site export --- .github/workflows/ci.yml | 6 +- site/next.config.js | 2 +- {assets => site/public}/CNAME | 0 site/src/app/favicon.ico | Bin 15406 -> 0 bytes site/src/app/page.tsx | 256 +++++++++++++++++++++++++++++++++ site/src/components/Button.tsx | 4 +- 6 files changed, 263 insertions(+), 5 deletions(-) rename {assets => site/public}/CNAME (100%) delete mode 100644 site/src/app/favicon.ico create mode 100644 site/src/app/page.tsx diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 79473f1..6c49438 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -15,8 +15,10 @@ jobs: cd scripts npm install node generate.mjs - cp -r ../assets/* ../dist + cd ../site + npm install + npm run build - uses: JamesIves/github-pages-deploy-action@4.1.1 with: branch: gh-pages - folder: dist + folder: site/out diff --git a/site/next.config.js b/site/next.config.js index 767719f..75a150c 100644 --- a/site/next.config.js +++ b/site/next.config.js @@ -1,4 +1,4 @@ /** @type {import('next').NextConfig} */ -const nextConfig = {} +const nextConfig = { output: 'export' } module.exports = nextConfig diff --git a/assets/CNAME b/site/public/CNAME similarity index 100% rename from assets/CNAME rename to site/public/CNAME diff --git a/site/src/app/favicon.ico b/site/src/app/favicon.ico deleted file mode 100644 index ac3baca844185cd32423e7fab9297d22a30e2b71..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 15406 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 P#{d2OzdP{%Vh8>YiI1vQ diff --git a/site/src/app/page.tsx b/site/src/app/page.tsx new file mode 100644 index 0000000..5448c4b --- /dev/null +++ b/site/src/app/page.tsx @@ -0,0 +1,256 @@ +import { Container } from '@/components/Container' +import { Footer } from '@/components/Footer' +import { Hero } from '@/components/Hero' +import { Introduction } from '@/components/Introduction' +import { NavBar } from '@/components/NavBar' + +export default function Home() { + return ( + <> + + + +
+ This aims to be the world’s most comprehensive email deliverability checklist. (Work in progress!)

+

If you’re sending outbound emails, you should follow this checklist to ensure that your emails are delivered to the inbox and not marked as spam. This checklist is based on the experience of sending tons of of outbound emails, and it’s open source to make sure we have the most recent and relevant information. Contributions are welcome!

+

Checklist

+ +

Custom domains and mailboxes

+

Coming soon

+

Additional domains

+
+

tl;dr: Use separate domains for outbound, ideally buy a few .com domains using your brand name.

+
+

You should not use your primary domain to send outbound, or for anything with high volume and potential for reputation damage. Instead, you should use separate domains for outbound. This is because if your primary domain is flagged as spam, it will affect your entire business, and you will have to spend a lot of time and effort to get it unflagged. If you use a separate domain for outbound, you can simply stop using it and switch to a new domain.

+

It’s recommended to purchase one or more .com domains (don’t use other TLDs, especially not free ones) using your brand name. For example, if your primary domain is example.com, you can purchase examplehq.com and getexample.com as additional domains, or more specific to your line of business, for example cleverclipvideos.com.

+

DNS records

+
+

tl;dr: Set up SPF, DKIM, and strict DMARC records for each of your additional domains.

+
+

It’s extremely important to set up your DNS records correctly, as this is the first thing mailbox providers check when determining whether an email is spam or not. You should set up the following DNS records for each of your additional domains.

+
SPF
+

The Sender Policy Framework (SPF) is a DNS record that specifies which mail servers are allowed to send email on behalf of your domain. It’s recommended to use a tool to generate your SPF records or use standard ones provided by your mailbox provider. For example, if you’re using Google Workspace, your SPF record will look like this:

+
v=spf1 include:_spf.google.com ~all
+

In the above example, _spf.google.com is a standard SPF record provided by Google Workspace, and ~all means that if the email is not sent from one of the servers specified in the SPF record, it should be soft-failed, i.e., marked as spam but still delivered to the inbox. Other options are -all (hard-fail, i.e., marked as spam and not delivered to the inbox), ?all (neutral, i.e., not marked as spam), and +all (allow all servers to send email on behalf of your domain, i.e., not marked as spam). It’s recommended to use ~all or -all as your SPF record, and only include servers that you’re using to send email.

+
DKIM
+

The DomainKeys Identified Mail (DKIM) is a DNS record that allows the recipient to verify that an email was sent and authorized by the owner of that domain. It’s recommended to use the standard DKIM record provided by your mailbox provider. For example, if you’re using Google Workspace, you can generate a DKIM record in the Google Admin console and add it to your DNS records.

+
DMARC
+

The Domain-based Message Authentication, Reporting, and Conformance (DMARC) is a DNS record that specifies how mailbox providers should handle emails that fail SPF or DKIM checks. An example DMARC record is:

+
v=DMARC1; p=reject; rua=mailto:rua@example.com; ruf=mailto:ruf@example.com
+

In the above example, p=reject means that if an email fails SPF or DKIM checks, it should be rejected, i.e., marked as spam and not delivered to the inbox. Other options are p=quarantine (soft-fail, i.e., marked as spam but still delivered to the inbox) and p=none (no action taken, i.e., not marked as spam). It’s recommended to use p=reject as your DMARC record to ensure that only emails sent from your authorized servers are delivered to the inbox after testing that your SPF and DKIM records are set up correctly. If you’re unsure about your configuration, you can use p=quarantine in the beginning to ensure that emails are still delivered and then switch to p=reject after testing.

+

You should also specify a rua and ruf email address to receive reports about emails that fail SPF or DKIM checks. These reports are sent by mailbox providers to the specified email address, and can be used to debug any issues with your SPF and DKIM records. It’s recommended to use a separate email address for this purpose, and not your primary email address; it’s easiest to use a third-party hosted service that provides this functionality.

+
Other records
+

You can additionally set up additional DNS records such as BIMI, MTA-STS, and TLS-RPT, but these are not necessary and can be set up later if you wish to. BIMI in particular is an interesting candidate, as it allows you to specify a logo that will be displayed next to your emails in the inbox, but it’s not widely supported yet and can be very expensive to set up, especially for a large number of domains. In general, you should be good to go with strict DMARC using properly set SPF and DKIM records.

+

Redirects

+
+

tl;dr: Use a HTTP 301 redirect from your additional domains to your primary domain, and ideally include UTM parameters and a wildcard redirect.

+
+

It’s recommended to use a HTTP 301 redirect from your additional domains to your primary domain. This is because if you use a separate domain for outbound, you will likely want to redirect recipients to your primary domain when they click on a link in your email or types the address manually. For example, if you’re sending an email from user@exampleapp.com and the recipient goes to exampleapp.com (email clients such as Superhuman make this very easy), they should be redirected to example.com.

+

You can additionally set up UTM parameters when redirecting your additional domains to your primary domain to track where the traffic is coming from. For example, if you’re sending an email from user@exampleapp.com and the recipient goes to exampleapp.com, you can redirect them to example.com/?utm_source=exampleapp.com&utm_medium=email&utm_campaign=outbound-domain-redirect. This way, you can track how many people are visiting your primary domain from your additional domains, and how many of them are converting.

+

Ideally, you should also include a wildcard redirect so that all pages on your primary domain also work on your additional domains. For example, exampleapp.com/pricing should redirect to example.com/pricing. This way, you can use the standard links on your website in your outbound emails, and they will work on your additional domains as well, with the exception of using the additional domain in the URL instead of the primary domain.

+

Mailboxes

+

We recommend using a trusted mailbox provider like Google Workspace on your additional domains and setting up a few mailboxes for each domain while strictly enforcing a maximum number of emails sent per day per mailbox and having backup mailboxes.

+

Mailbox providers

+
+

tl;dr: Use Google Workspace on your additional domains, and Microsoft 365 for enterprises.

+
+

There are many mailbox providers and enthusiasts can host their own mail servers, but the most popular ones are Google and Microsoft. It’s not recommended to use your own mail server, as it’s very difficult to set up and maintain, and you will likely have a low deliverability rate because of limited IP address reputation. Instead, you should use a third-party mailbox provider, such as Google Workspace or Microsoft 365, which are both very easy to set up and maintain, and have a high deliverability rate because of their high IP address reputation. Note that this is limited to using their paid business email offerings, not their free consumer email offerings. When in doubt, use Google Workspace, unless your target audience is more often using Microsoft 365, which is more common in the enterprise.

+

You should also not use a third-party email service provider (ESP) such as SendGrid or AWS SES, as they most often used for transactional emails and marketing emails, and have strict anti-spam policies. They also more likely end up in “Promotions” or “Updated” folders, whereas emails sent from a trusted mailbox provider are more likely to end up in the “Primary” inbox. To a lesser extent, you can consider more affordable providers like Zoho Mail, but they are not as reliable as Google or Microsoft. Some ESPs also offer dedicated IP addresses, but these are not recommended because their IP address reputation is not as good as Google or Microsoft, especially if you’re starting out.

+

You can also optimize for having the same mailbox provider as your recipient, as this can also increase your deliverability rate. For example, if you’re sending an email to someone with an address hosted on Google, you should use Google Workspace to send the email. This is because mailbox providers are more likely to deliver emails from the same provider, and slightly less likely to deliver emails from different providers. You can use the DNS records of the recipient’s domain to determine which mailbox provider they are using and then use the same provider to send the email, but this is probably overkill for many use cases.

+

Rotating mailboxes

+
+

tl;dr: Use a few mailboxes for each domain, and have a backup mailbox for each active mailbox.

+
+

It’s recommended to have at least two mailboxes for each domain, one active and one backup. This is because if your active mailbox is flagged as spam, you can switch to your backup mailbox and continue sending emails. If you wish to, you can also have a backup mailbox provider, but this is not necessary unless you have a very high volume of emails or a high risk of being flagged as spam. If you have a backup mailbox provider, you should use separate domains for each provider instead of using subdomains.

+

A good rule of thumb is to have one backup mailbox for every 3 active mailboxes. For example, if you have 3 active mailboxes, you should have 1 backup mailbox, and if you have 6 active mailboxes, you should have 2 backup mailboxes. This is because if you have a high volume of emails, you’re more likely to be flagged as spam, and therefore more likely to need a backup mailbox.

+

When a mailbox gets a lot of spam complaints, it’s likely to be flagged as spam by mailbox providers, and therefore you should stop using it immediately. You should also stop using a mailbox if you’re getting a lot of bouncebacks, as this is also likely to affect your deliverability rate. If you’re using a backup mailbox, you can switch to it immediately, and if you’re not, you should create a new mailbox and start warming it up. For the next few weeks, you should continue to warm up your previous mailbox and only restart using it after it has a good sender reputation again.

+

Sending limits

+
+

tl;dr: Strictly enforce a maximum number of emails sent per day per mailbox, starting with 30 emails per day per mailbox, and a maximum of 3 active mailboxes per domain.

+
+

You should strictly enforce a maximum number of emails sent per day per mailbox, and scale up the number of active mailboxes as you want to send more emails. This is because if you send too many emails from a single mailbox, it’s likely to be flagged as spam by mailbox providers. You should also not have more than a few active mailboxes per domain, so if you want to send more emails, you should use purchase additional domains and create new mailboxes for them.

+

We recommend a maximum of 30 emails per day per mailbox, and a maximum of 3 active mailboxes per domain when you’re getting started. This means that you can send up to 90 emails per day per domain. This is a good starting point, and you can increase the number of emails per day per mailbox and the number of active mailboxes per domain as your domain reputation increases. You should also not send more than 1 email every 10-30 minutes per mailbox, because that’s the average time it takes for a human to write and send an email. The more you can mimic human behavior, the better for your deliverability, so you should aim to send emails at a human-like pace, for example one email every 30 minutes and distributed randomly throughout the day.

+
    +
  • Start with low volume
  • +
  • Have a consistent volume and don’t have spikes
  • +
  • Scale up when you have “message market fit”
  • +
+

Email warming

+
+

tl;dr: Start with 1 email per day and increase by 2 emails every day until you reach 30 emails per day after two weeks, and then continue to warm up your mailbox while keeping the same maximum number of emails per day, randomizing it.

+
+

Email warming is the process of gradually increasing the number of emails you send and receive from a new mailbox to establish a good sender reputation with mailbox providers. This is done by sending a small number of emails at first, and then gradually increasing the number of emails sent over time, and having a percent of those emails replied to. This makes the mailbox provider believe that the emails sent are worth replying to, and are therefore not likely spam.

+

Always keep warming

+

Regardless of whether you have a completely fresh mailbox or one that’s already been used in the past, it is of paramount importance that you always continue to warm up your mailboxes. This is to maintain your sender reputation and ensure that your emails are delivered to the inbox, and if you have a good reputation today does not necessarily mean that you will have a good reputation tomorrow.

+

What’s interesting is that some deliverability experts no longer recommend warming as they suggest that it’s trivial to detect and therefore disregard warming emails, but until this is of general consensus, it’s best to continue to warm up your mailboxes.

+

For new mailboxes

+

Immediately after creating a new mailbox, you should start warming it up. Most email warming tools offer a ramp-up option, rather than a flat number of emails per day, which is recommended. For example, a configuration could be to start from 1 email per day and increase by 2 emails every day (i.e., 1, 3, 5, 7, etc.) until you reach 30 emails per day after two weeks. This is because mailbox providers are more likely to flag a sudden increase in email volume as spam.

+

In the beginning, you can have a high reply rate of 30-50%, and then drop it a little lower after the initial ramping up period is over. You don’t want to have a reply rate that’s too low or too high, because both extremes are likely to be flagged as spam.

+

tl;dr:

+
    +
  • Ramping up period: ~14 days
  • +
  • Total maximum emails per day: ~30
  • +
  • Daily increase: 2 ±2
  • +
  • Reply rate: 30-50%
  • +
+

Randomization is important

+

Even if you ramp-up, it’s preferred to randomize the number of emails sent per day. For example, instead of 1, 3, 5, 7, 9, etc., it could be 1, 2, 5, 6, 9, etc., i.e., keeping the same general pattern but randomizing the number of emails sent per day. This is because mailbox providers could be likely to flag a clear pattern as spam. An easy way to implement this behavior is to randomize the daily increase (±2).

+

You should also randomize the time of day at which emails are sent, and to which providers. It’s important to have diversity in providers (e.g., Gmail, Outlook, etc.) and in the time of day (e.g., 9:19 am, 11:37 am, 2:06 pm, etc.). Most email warming tools are configured to do this by default.

+

After ramping up

+

After the initial ramping up period, you should continue to warm up your mailbox while keeping the same maximum number of emails per day, randomizing it. For example, send between 25 and 35 emails per day with a reply rate of 30%-40%. This is because you want to maintain your sender reputation as you scale your email volume.

+

tl;dr:

+
    +
  • Total maximum emails per day: 30 ±5
  • +
  • Reply rate: 30-40%
  • +
+

Positive and negative actions

+

Positive actions include replies, marking as important, etc., while negative actions include marking as spam, unsubscribing, etc. Since we want to optimize for positive actions, you can employ certain tricks, such as asking a question. Even if it’s a simple yes/no question, it’s more likely to get a reply and therefore a positive action.

+

Body content

+
+

tl;dr: Personalize the messaging, randomize the body content, and avoid spammy words, images, links, and attachments.

+
+

Perhaps the most important part of your email is the body content. This is because mailbox providers are increasingly using machine learning to determine whether an email is spam or not, and the body content is one the most important factors in this decision. And of course, sending the right message to the right person is the most important part of your outbound strategy, if you can’t control for the right time.

+

Personalize the messaging

+

Using variables like “Hi {firstName}” is no longer enough as recipients are receiving too many outbound emails and can easily tell if it’s a template. The more personalized your message, the less likely it is to be flagged as spam by recipients which does a lot of damage to your sending reputation. You should either write personalized emails manually, or use an automated tool like that does this for you, for example using a large language model. At the very least, you should personalize the first sentence of your email to make it seem like it’s not a template.

+

Randomize the body content

+

Similar to randomizing the number of emails sent per day, you should also randomize the body content of your emails. This is because mailbox providers are likely to flag a clear pattern as spam. In general, the more randomization you have, the better for your deliverability.

+

One way to easily get started is to use the spintax strategy, where you have multiple variations of the same sentence, and the outbound tool will randomly select one of them. For example, you could have the following variations of the same sentence:

+
    +
  • I’m reaching out to you because I saw that you’re working at {companyName}.
  • +
  • I’m reaching out to you because I saw online that you’re working for {companyName}.
  • +
  • I thought of reaching because I saw that you’re working at {companyName}.
  • +
+

If this sounds too easy to be very useful, it’s because it probably is. These days, it’s best that you go further than having just a few variations of a few words in the content. Ideally, the entire email will be generated by a large language model like GPT-4, so that it’s completely unique and can be highly personalized, or written manually.

+

What not to include

+

It’s best to avoid including anything that could be flagged as spam by mailbox providers. Ideally, your email should be as simple as possible, totally in plain text without any fancy HTML. Of course, this is not always possible, so you should try to avoid words and phrases that are likely to be flagged as spam, and include as few images and links as possible.

+

Spammy words

+

Words such as “risk-free” and phrases like “additional income” are very often found in scam emails, and are therefore likely to be flagged as spam. Please don’t include Nigerian princes in your email!

+

Although articles such as 188 Spam Words to Avoid: How to Stay Out of Email Spam Folders help you avoid spammy words, it’s best to use an API that detects spammy words in your email content and warns you about them before you send the email.

+

Since mailbox providers have dynamic spam word lists and increasingly use machine learning to detect spam, so it’s possible that copy that works for a certain period of time will stop working later, so keep an eye on your spam rate and adjust your copy accordingly (see Key metrics below).

+

It’s also recommended to use regular sentence (or lower) case copy, as uppercase copy is often used in spam emails. Similarly, you should avoid using too many exclamation marks.

+

Images

+

Images are often used in spam emails, and are therefore likely to be flagged as spam. If you must include an image, make sure it’s not the only thing in your email, and that it’s not too large, and ideally not in the first email but in subsequent follow-ups.

+

You should also include an alt attribute in the image tag, which is good for accessibility but can also help with deliverability. This is because if the image is not loaded, the alt attribute will be displayed instead and the mailbox provider can also use this text in their spam detection algorithm.

+

Although it’s good to have alternate text on images, it’s not a good idea to have text in images. This is because putting text in images used to be a common way to bypass spam filters by fraudsters, so your images should not have a lot of text in them (a little bit like a logo is usually okay).

+

Tracking pixels are usually 1x1 pixel GIFs which may reduce deliverability, so make sure any “real” images you include are larger than 1x1 pixel to avoid being flagged as a tracking pixel. You should also aim to have a short, human-readable URL for the image, and not a long, random URL that looks like a tracking pixel.

+ +

Almost all spam emails include links, so including even one link can increase the likelihood of your email being flagged as spam. Of course, sometimes you need a call-to-action link, so try to keep it to one link per email, and ideally not in the first email but in subsequent follow-ups.

+

It’s also recommended for the link to be a short, human-readable URL, and not a long, random URL that looks like a tracking pixel. You should also avoid using URL shorteners, as they are often used in spam emails, instead preferring to use your mailbox’s domain wherever possible. For example, if you’re sending an email from user@examplehq.com when your primary domain is example.com, you should use a link like https://examplehq.com/your-page. If you want to track clicks, you can personalize the URL using a short slug, e.g., https://examplehq.com/your-page/patrick-stripe for an email sent to patrick@stripe.com from user@examplehq.com.

+

Attachments

+

Attachments are in general a bad idea, as they are often used in spam emails, especially executable or compressed files. Although PDFs are frequently used in proposals and presentations, they are able to contain malicious code and connect to the internet, so they are often flagged as spam. You should not include attachments in your first email, and ideally not in subsequent follow-ups either, only sending them when requested by the recipient.

+

The only exception is sending calendar invites, but these are usually open-in .ics files, so you should still avoid sending them unless requested.

+

Keep markup similar to human emails

+

Coming soon

+
    +
  • Gmail uses divs instead of paragraphs
  • +
  • When quoting text, use exact markup
  • +
  • Popular HTML templates go to promotions
  • +
+

Opt-out and unsubscribe

+

Coming soon

+
    +
  • Unsubscribe link is good because people don’t mark as spam
  • +
  • Asking for “If you’re ot interested, let me know” is better than marking as spam
  • +
+

Subject line

+

Coming soon

+
    +
  • Subject copy determines open rate, higher the better for deliverability
  • +
  • Iterate, A/B test, keep an eye on open rate
  • +
+

Open and click tracking

+

Coming soon

+

Right people, right time

+

Coming soon

+

Targeting

+
    +
  • It’s not good when people mark you as spam
  • +
  • If you reach out to the wrong people, they will mark you as spam
  • +
  • Clearly define your target audience
  • +
+

Coming soon

+

Buying intent

+

Coming soon

+
    +
  • Spam traps exist when you buy email lists
  • +
+

Email verification

+

Coming soon

+

Scheduling

+

Coming soon

+

Days and timezones

+

Coming soon

+

Randomization

+

Coming soon

+

Key metrics

+

Coming soon

+
    +
  • Open rate, click rate, click-to-open rate
  • +
  • Replies, bouncebacks, spam complaints, unsubscribes
  • +
  • Inbox placement rate, spam placement rate, missing rate
  • +
  • Spam traps, blocklists
  • +
  • Google Postmaster Tools
  • +
+` }} /> +
+