Using Smart CSS to Time Your Wonderful Newsletter Popup
Tags: css, javascript, html, webdev
Published: 2019-01-29 13:58:20

---
title: Using Smart CSS to Time Your Wonderful Newsletter Popup
published: true
cover_image: https://thepracticaldev.s3.amazonaws.com/i/fwr7r0oq5epbr1nf2kvn.jpeg
canonical_url: https://pqina.nl/blog/using-smart-css-to-time-your-wonderful-newsletter-popup/
description: By reading out page variables with JavaScript and storing them in data attributes we can use them in CSS to toggle elements on the page
tags: css, javascript, html, webdev
---

In the [previous article on Smart CSS](https://dev.to/rikschennink/applying-styles-based-on-the-user-scroll-position-with-smart-css-5c/) we used the user's scroll position to trigger a floating navigation header.

> This article was originally published on [my personal blog](https://pqina.nl/blog/using-smart-css-to-time-your-wonderful-newsletter-popup/)

Let's take it a step further and see if we can use this technique to determine if a user is interested in subscribing to our newsletter. Imagine this is a newsletter on a website that presents the user with an article like the one you're reading now. The goal is to trigger the user into subscribing so we can send a notification if a new article is published in the future.

We'll assume the marketing department has us at gunpoint and is ordering us to show a popup with a subscription form. Personally, I would rather show the form beneath the article, inlined in the page, but you probably know how these things go.


## How to determine the best moment to show this popup?

Imagine you're shopping in real life, you wander into a random shop, you haven't even crossed the doorstep and the shop keeper jumps in your face and asks you if you want to receive their monthly newsletter. This would be weird, right?

**On the internet, the above behavior is somehow the norm.**

Maybe it would be a good start to gauge the user's interest in our newsletter before we ask. How do we determine this potential interest? Let's go back to our random shop.

Suppose the following:

- I've visited the shop before
- I've spent some time wandering the shop
- I've actually purchased something
- I've had a positive interaction with the shop keeper

If a couple of these had a green light, I would still not welcome the shop keeper jumping in front of me, but I certainly would not mind them asking me at the counter, and if that would happen, I might even subscribe.

Are there equivalents to this in our online environment? I can think of a couple of data points, but do let me know in the comments if you have any other suggestions.

- The user spent some time on the site
- The user has been reading the page
- The user has spent some time on the current page
- The user has made a purchase


## Translating these data points to variables

To determine if the user has visited the site before we can store the time she spent on our site in a session variable using `localStorage`. By calculating the time spent on each page and saving it to `localStorage` at a certain interval we can know how long the user has been browsing the site. And thus, we can determine how familiar the user is with our platform, are we a random shopkeeper? Or have we met before?

By measuring how far the user has scrolled down on the page we can determine if he is interacting with the site. If the page presents an article this might give us some information on how far along the article the user has read. Combine this with the time user has spent on the page and we could guestimate the user has read the article or is nearly done reading it. If the user has taken the time to read the article, then that might mean he's interested in our content, he's "purchased" our content so to speak. Of course, if you run a webshop you could keep track of actual purchases as well.

The techniques used in the demo below are mostly the same as in the earlier article. I've introduced a function that serves as an updater for the data attributes. And another addition is the `stack` function.

```js
const stack = (value, step) => {
  // round the value to the nearest value divisible by step
  // if value is 37 and step is 10 the result is 30
  value = Math.floor(value / step) * step;

  // 30 will be our first value
  const parts = [value];

  // now we subtract 10 each iteration till we reach 0
  while (value > 0) {
    value -= step;
    parts.push(value);
  }

  // reverse the array so it goes from 0 to 30 insted of 30 to 0
  return parts.reverse();
}
```

This function receives a `value` and a `step` parameter. Suppose the `value` is set to `50` and the `step` is set to `10`, the function will return this array: `[0, 10, 20, 30, 40, 50]`. We use this array to store multiple values in our data attributes.

For example, suppose the user has scrolled 50% of the page. The `data-vertical-scroll-progress` attribute is then set to `"0 10 20 30 40 50"`. This allows us to use [CSS attribute selectors](https://developer.mozilla.org/en-US/docs/Web/CSS/Attribute_selectors) to determine if the user has scrolled at least 30 percent of the page. The `~=` comparison checks if the set value contains in a white space separated list of items.

```html
<html data-vertical-scroll-progress="0 10 20 30 40 50">
    <!-- Your website here -->
</html>
```

```css
html[data-vertical-scroll-progress~='30'] {
   /* user has scrolled down 30% */
}
```

Let's combine all our tests and make this a reality. The below demo will show the popup when you've scrolled down 50% and have been on the page for 30 seconds.

{% codepen https://codepen.io/rikschennink/pen/vbKjmJ default-tab=js,result %}

I'm super interested in other ways we can use these techniques, so if you have any ideas, share them below!