Content Gating Example Code (HTML, CSS, JS)
Last week we looked at the best implementation that I’ve ever seen of content gating on the First Round Capital blog.
This week I’d like to take a stab at reproducing that example in simple HTML, CSS, and Javascript. The goal for this week is to give you a head start should you decide to ever experiment with gating on your blog.
Let’s dive right into the code.
Generic blog layout
For example purposes, we’ll start with a super generic blog post layout.
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>Simple Blog Layout</title>
<style>
* { padding: 0; margin: 0; text-align: left; }
body { background: #253540; color: #FFF; font-family: sans-serif; font-size: 21px; text-align: center; }
h1 { font-size: 43px; font-weight: 300; margin-bottom: 53px; }
header { border-bottom: 1px solid #394956; font-size: 23px; font-weight: 300; margin-bottom: 53px; padding: 53px; text-transform: uppercase; }
p { color: #93A1AF; line-height: 33px; margin-bottom: 43px; }
section { margin: 0 auto; max-width: 768px; width: 80%; }
</style>
</head>
<body>
<header>Blog Example</header>
<section>
<div class="content">
<h1>Blog Title</h1>
<p>Blog content here...</p>
</div>
</section>
</body>
</html>
Here’s what that code looks like in the browser and here’s a quick screenshot:
Nothing fancy. We just need a simple generic blog layout to add out gating example to.
Fade out effect
The next step will be to code up a little fade out effect. Here’s what the code looks like:
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>Simple Blog Layout</title>
<style>
/* Basic Blog Styles */
* { padding: 0; margin: 0; text-align: left; }
body { background: #253540; color: #FFF; font-family: sans-serif; font-size: 21px; text-align: center; }
footer { font-size: 14px; margin: 53px auto 100px; max-width: 768px; width: 80%; }
h1 { font-size: 43px; font-weight: 300; margin-bottom: 53px; }
header { border-bottom: 1px solid #394956; font-size: 23px; font-weight: 300; margin-bottom: 53px; padding: 53px; text-transform: uppercase; }
p { color: #93A1AF; line-height: 33px; margin-bottom: 43px; }
section { margin: 0 auto; max-width: 768px; width: 80%; }
/* Gating Fade Out Styles */
.gate {
display: none;
}
.gated {
height: 1000px;
overflow-y: hidden;
position: relative;
}
.gated .gate {
background: linear-gradient( rgba(37,53,64,0), rgba(37,53,64,1) );
display: block;
height: 1000px;
left: 0;
position: absolute;
right: 0;
top: 0;
z-index: 2;
}
</style>
</head>
<body>
<header>Blog Example</header>
<section>
<div class="content gated">
<div class="gate"></div>
<h1>Blog Title</h1>
<p>Blog content here...</p>
</div>
</section>
<footer>© 2018</span> All rights reserved.</footer>
</body>
</html>
Again here’s what that code looks like in the browser and here’s a screenshot:
At this point, all we have to do to turn gating on for any blog post will be to add a .gated class to the .content
section. This sets a fixed height of 1000px on the content div and activates an absolutely positioned .gate
div which creates the desired fade out effect.
Call to action
Next up we’ll introduce the CTA to collect email addresses:
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>Simple Blog Layout</title>
<style>
/* Basic Blog Styles */
* { padding: 0; margin: 0; text-align: left; }
body { background: #253540; color: #FFF; font-family: sans-serif; font-size: 21px; text-align: center; }
footer { font-size: 14px; margin: 53px auto 100px; max-width: 768px; width: 80%; }
h1 { font-size: 43px; font-weight: 300; margin-bottom: 53px; }
header { border-bottom: 1px solid #394956; font-size: 23px; font-weight: 300; margin-bottom: 53px; padding: 53px; text-transform: uppercase; }
p { color: #93A1AF; line-height: 33px; margin-bottom: 43px; }
section { margin: 0 auto; max-width: 768px; width: 80%; }
/* Gating Fade Out Styles */
.gate { display: none; }
.gated { height: 1000px; overflow-y: hidden; position: relative; }
.gated .gate { background: linear-gradient( rgba(37,53,64,0), rgba(37,53,64,1) ); display: block; height: 1000px; left: 0; position: absolute; right: 0; top: 0; z-index: 2; }
/* Gating CTA */
.gate_cta {
background: #F9FAFA;
border-radius: 6px;
margin: 0 auto;
max-width: 440px;
padding: 43px 33px;
position: relative;
top: 50%;
text-align: center;
transform: translateY(-50%);
width: 100%
}
.gate_cta button {
background: #3197D6;
border: none;
border-radius: 4px;
color: #FFF;
display: block;
font-size: 18px;
margin: 0 auto 18px;
padding: 13px 33px;
}
.gate_cta .gate-skip {
color: #93A1AF;
display: inline-block;
font-size: 12px;
font-weight: 300;
text-decoration: none;
}
.gate_cta .gate-skip:hover {
text-decoration: underline;
}
.gate_cta h3 {
color: #253540;
font-size: 26px;
font-weight: 600;
margin-bottom: 0;
text-align: center;
}
.gate_cta input {
border: 1px solid #D6DDE3;
border-radius: 2px;
font-size: 18px;
margin-bottom: 23px;
padding: 13px;
width: 100%;
}
.gate_cta p {
font-size: 16px;
margin-bottom: 23px;
text-align: center;
}
</style>
</head>
<body>
<header>Blog Example</header>
<section>
<div class="content gated">
<div class="gate">
<div class="gate_cta">
<h3>Don't Miss a Single Post 🤟</h3>
<p>Join over 32,000 other weekly newsletter subscribers.</p>
<input type="email" placeholder="Enter your email" required />
<button>Subscribe</button>
<a href="#" class="gate-skip">No thanks</a>
</div>
</div>
<h1>Blog Title</h1>
<p>Blog content here...</p>
</div>
</section>
<footer>© 2018 All rights reserved.</footer>
</body>
</html>
Here’s a live preview of this code, and a screenshot:
Again, the “No thanks” link is key here. You don’t want to drive away visitors by forcing them to enter their email. The goal here is to collect as many email addresses as you can, but to never block someone from reading your content if they aren’t interested in joining your list.
Hooking it all up
The last thing we need to do is add a bit of JavaScript to bring everything to life. There are a couple of conditions that we want to account for here:
- If a visitor enters their email, they should never see any additional content gates on any other posts from that point forward.
- If a visitor loads the page, but neither submits the form, nor clicks “No thanks”, the next time they load a blog post on your site, they should still see the gate.
- If a visitor clicks “No thanks”, the gate should immediately disappear, and they should not see any additional content gates.
Now let’s take a look at the code:
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>Simple Blog Layout</title>
<style>
/* Basic Blog Styles */
* { padding: 0; margin: 0; text-align: left; }
body { background: #253540; color: #FFF; font-family: sans-serif; font-size: 21px; text-align: center; }
footer { font-size: 14px; margin: 53px auto 100px; max-width: 768px; width: 80%; }
h1 { font-size: 43px; font-weight: 300; margin-bottom: 53px; }
header { border-bottom: 1px solid #394956; font-size: 23px; font-weight: 300; margin-bottom: 53px; padding: 53px; text-transform: uppercase; }
p { color: #93A1AF; line-height: 33px; margin-bottom: 43px; }
section { margin: 0 auto; max-width: 768px; width: 80%; }
/* Gating Fade Out Styles */
.gate { display: none; }
.gated { height: 1000px; overflow-y: hidden; position: relative; }
.gated .gate { background: linear-gradient( rgba(37,53,64,0), rgba(37,53,64,1) ); display: block; height: 1000px; left: 0; position: absolute; right: 0; top: 0; z-index: 2; }
/* Gating CTA */
.gate_cta { background: #F9FAFA; border-radius: 6px; margin: 0 auto; max-width: 440px; padding: 43px 33px; position: relative; top: 50%; text-align: center; transform: translateY(-50%); width: 100% }
.gate_cta button { background: #3197D6; border: none; border-radius: 4px; color: #FFF; display: block; font-size: 18px; margin: 0 auto 18px; padding: 13px 33px; }
.gate_cta .gate-skip { color: #93A1AF; display: inline-block; font-size: 12px; font-weight: 300; text-decoration: none; }
.gate_cta .gate-skip:hover { text-decoration: underline; }
.gate_cta h3 { color: #253540; font-size: 26px; font-weight: 600; margin-bottom: 0; text-align: center; }
.gate_cta input { border: 1px solid #D6DDE3; border-radius: 2px; font-size: 18px; margin-bottom: 23px; padding: 13px; width: 100%; }
.gate_cta p { font-size: 16px; margin-bottom: 23px; text-align: center; }
</style>
</head>
<body>
<header>Blog Example</header>
<section>
<div class="content gated">
<div class="gate">
<div class="gate_cta">
<h3>Don't Miss a Single Post 🤟</h3>
<p>Join over 32,000 other weekly newsletter subscribers.</p>
<form class="newsletter-signup">
<input type="email" placeholder="Enter your email" required />
<button>Subscribe</button>
</form>
<a href="#" class="gate-skip">No thanks</a>
</div>
</div>
<h1>Blog Title</h1>
<p>Post content here...</p>
</div>
</section>
<footer>© <span class="year"></span> All rights reserved.</footer>
<script>
(function(){
updateCopyrightYear();
gateCheck();
gateEvents();
// -------------------------------------------------------
// FUNCTIONS
// -------------------------------------------------------
function gateCheck() {
// Gate is shown by default. Let's check if it should be removed
var hideGate = localStorage.getItem('gate-hide') || false;
if (hideGate) {
gateHide();
}
}
function gateEvents() {
// Dismiss gate when anyone clicks "No thanks"
document.querySelector('.gate-skip').addEventListener('click', function(e) {
e.preventDefault();
// Save preference to localstorage
gatePrevent();
// Hide the gate immediately
gateHide();
});
// Handle form submission
document.querySelector('.newsletter-signup').addEventListener('submit', function(e) {
e.preventDefault();
// Do something with the form data here...
// Then...
// Save preference to localstorage
gatePrevent();
// Hide the gate immediately
gateHide();
});
}
function gateHide() {
// Remove the .gated class from .content which hides the entire .gate div
document.querySelector('.content').classList.remove('gated');
}
function gatePrevent() {
// Prevent the gate from being shown from this point forward
localStorage.setItem('gate-hide', true);
}
function updateCopyrightYear() {
// Updating the copyright year with JS so that it's always current
document.querySelector('.year').innerHTML = new Date().getFullYear();
}
})();
</script>
</body>
</html>
That’s it! Here’s a final preview of everything in the browser.
One last word on Duct tape and super glue
As with any of my code examples, this is a pretty bare bones approach. When testing any new onboarding initiative I’m a big fan of using what I call duct tape and super glue to test your hypotheses.
What that means is that you don’t have to spend hours writing pristine code. You don’t have to write unit tests. Don’t make too big of a fuss over your v1 iterations because there’s a decent chance that you may want to scrap the entire initiative after gathering some data.