Building WhyPride.com

Tanner Jones
13 min readJul 1, 2021

I built whypride.com as part of my passion project: ExplainGood, where I try to, you know, explain stuff good.

Why Pride is a response to this whiny question that kept coming up from the more bigoted corners of my social media during pride month:

“why do gay people even need pride month?”

So I set out to find the answer, and then display it in a way that would:

  1. Highlight the huge shift in public opinion that “pride” has helped create
  2. Change the playing field of the question from “right & wrong” (which is inferred by the fact that the question is actually just complaining that a group of people they don’t like are getting attention), to something a little more concrete: “winning & losing”.
    I wanted to shift the question in such a way so that the people who are complaining about how “pride” seems to get louder and louder every year realize that they are right… but that the reason is that the number of people like them is shrinking… and they probably are going to abandon their opinions sometime soon as well.
  3. I also wanted the display to have at least a small, positive, persuasive effect on people who read it.

To do it, I needed fun, reliable data, and a cool way to visualize the change. I decided on a one-page website that attempted to carry some of the swagger that the people at pudding.cool flex every single post.

The Data

So the data isn’t perfect (obviously the number of people who become allies isn’t exactly 4,430,000 every single year), but I feel like I got pretty close. Here’s how I arrived at that number.

First, I estimated how many people would from each generation will be alive from now until 2040 by using this chart from Pew Research.

I also had to estimate how many people from Gen Alpha (born 2010–2024) and Gen Beta (2025–2039) would be “culturally relevant”.

Here’s what I mean by culturally relevant. A newborn exists as part of the population numbers, but they don’t have an opinion on gay marriage.

A 6-year-old might have an opinion on gay marriage (albeit an unsophisticated one), but I’m fairly certain that opinion is just a reflection of their caregiver.

I decided, based on my zero years of experience with child psychology, that I would just make a guess and try to estimate what portion of a generation was over 12 years old, and that their opinions should be included as part of the calculation.

I came up with this:

People with Opinions By Generation in the US

Next, I took the data from this Pew Research and this Gallup Poll and tried to estimate how opinions on gay marriage would change for the next 20 years based on the change in the last 16 years.

I also had to estimate what Gen Z, Gen Alpha, and Gen Beta would be, based on how each generation is more tolerant than the last. With data we have, each generation is, on average, around 10% more pro-gay marriage than the generation before it, so I decided to estimate conservatively and only increased Gen Z, Gen Alpha, and Gen Beta support by 5% compared to their prior generation.

I also had to guess how much opinions would change every decade. I decided to be conservative again: I took the average change in opinion for each generation from the previous decade and then divided it by 2. I used that number to determine how much support would grow until 2030. And then I divided it by 2 AGAIN to determine how support would grow between 2030 and 2040.

So to summarize, I think I made pretty conservative estimates on the support of growth because I’m basing everything off of the idea that LBGT support will grow twice as slow as what is actually happening in reality.

Oh, and also, I decided to cap support at 92%, based entirely on the fact that 5% of the US believes the earth is flat, and I imagine that if we can’t convince 5% of the population that the world isn’t flat, we probably should give ourselves a few percentage points of buffer for gay marriage.

This is what I came up with:

Estimated Gay Marriage Approval Rates By Generation

I was able to mix all of that data together to make a guess on how the total number of supporters increased over the years:

Estimated Number of People in the US that Support Gay Marriage

That’s a raw increase of 93.1 million allies from 2019 to 2040, or 4.43 million a year.

But I also wanted to estimate how many of those allies were people who changed their mind, not just Silents and Boomers being replaced by Alphas and Betas.

So I took the population averages of each generation from ’19-’30 and ‘30-’40 and then multiplied it by our change figures from above. Here were the results:

That’s 44.2 million people who will change their minds between 2019–2040. Or 2,105,000 per year.

Also important to note, not all Gen Alphas and Gen Betas are replacing anti-gay marriage Silents and Boomers. From now until 2030 there will be around 13million allies that pass away and another 13 million allies that pass away between 2030 and 2040.

In other words, 26 million new, young allies will be taking the mantle of 26 million before them.

So the data I need for the website is:

  • the # of allies per year (4,433,000)
  • # of ‘opinion changers’ per year (2,105,000)

The Code

Creating The Grids

I want to create four grids.

One that represents the total number of new allies

One that highlights the allies that are newer, younger generations

One that highlights the allies that are opinion changers

One that is constantly updating, showing the growing support for gay marriage in the US.

The first three grids are easy. I just create a javascript function that will add little pre-styled boxes to my page:


[...Array(365).keys()].forEach((elem, i) => {
/* box 1*/
const bigLgbtElem = document.createElement('div');
bigLgbtElem.classList.add("pop-chunk", "lgbt", "big-pop-chunk");
preGrid1Elem.append(bigLgbtElem);
/* box 2+3 */ const bigLgbtOpaqueElem = document.createElement('div');
bigLgbtOpaqueElem.classList.add("pop-chunk", "lgbt", "big-pop-chunk", "opaque")

const bigLgbtDieElem = document.createElement('div');
bigLgbtDieElem.classList.add("pop-chunk", "lgbt", "die", "big-pop-chunk");

const bigLgbtSwitchElem = document.createElement('div');
bigLgbtSwitchElem.classList.add("pop-chunk", "lgbt", "big-pop-chunk", "switch")

if (i <= 230) {
preGrid2Elem.append(bigLgbtDieElem);
preGrid3Elem.append(bigLgbtOpaqueElem);
}
if (i > 230) {
preGrid2Elem.append(bigLgbtOpaqueElem);
preGrid3Elem.append(bigLgbtSwitchElem);
}
})

Box 4 is a little harder.. The first part of the code is similar, I just have to make a ton of boxes:

var usPopulation = 330000000;
var boxPopSize = 12145;
var numberOfBoxes = Math.floor(usPopulation/boxPopSize)
var allyPercentage = 0.7;
var numberOfAllies = Math.floor(allyPercentage * numberOfBoxes);
[...Array(numberOfBoxes).keys()].forEach((elem, i) => {
if (i < numberOfAllies) {
const lbgtGridElem = document.createElement('div');
lbgtGridElem.classList.add("pop-chunk", "lgbt");
theGrid.append(lbgtGridElem);
}
if (i >= numberOfAllies) {
const blackGridElem = document.createElement('div');
blackGridElem.classList.add("pop-chunk", "black-targets");
theGrid.append(blackGridElem)
}
})

Then we have to write the function that switches over a random non-ally to an ally…

var displayAllyPercentage = allyPercentage;
var dailyGrowth = boxPopSize / usPopulation;
var changeMinds = () => {
var blackTargets = document.querySelectorAll(".black-targets");
var targetToChange = blackTargets[Math.floor(Math.random() * blackTargets.length)];
targetToChange.classList.add("lgbt");
targetToChange.classList.remove("black-targets");
}

Then we add it to a setInterval timer so that it runs on repeat and keeps track of the day

var tomorrow = new Date();
var dateOptions = {year: 'numeric', month: 'long', day: 'numeric'};
var timer = setInterval(function() {
if (displayAllyPercentage >= 0.92) {
clearInterval(timer);
}

changeMinds();
tomorrow.setDate(tomorrow.getDate() + 1);
var theDate = tomorrow.toLocaleDateString("en-US", dateOptions);
var dateDiv = document.getElementById('date-counter');
dateDiv.innerHTML = theDate;
displayAllyPercentage = displayAllyPercentage >= 0.92 ? 0.92 : displayAllyPercentage + dailyGrowth;
var percentageDiv = document.getElementById('percentage-counter');
percentageDiv.innerHTML = parseFloat(displayAllyPercentage * 100).toFixed(2) + "%";
}, 133);

I picked to switch the date forward once every 0.133 seconds because… idk. I messed around with it and it seemed fast enough to not be boring but slow enough that you could appreciate the incremental growth.

The rest of the code…

It was all pretty mundane: just regular ol’ HTML and CSS. There was one cool code snippet I found online though that I used to change the color of elements into a pride flag:

.lgbt {
background: linear-gradient(180deg, #FE0000 16.66%,
#FD8C00 16.66%, 33.32%,
#FFE500 33.32%, 49.98%,
#119F0B 49.98%, 66.64%,
#0644B3 66.64%, 83.3%,
#C22EDC 83.3%);
}

Speed

I wanted the website to be fast. I did a few things:

Image Speediness:

There are three images on the site, and two are not mine. They are the images from Pew Research that I have embedded on this page as well. I made them speedier by doing two things: adding a lazy loading attribute, and specifying the size. Here’s an example of them with and without:

<!-- Faster Example -->
<img loading="lazy" alt="population by generation" src="https://www.pewresearch.org/wp-content/uploads/2020/04/FT_20.04.27_GenerationSize_1.png" style="width: 600px; max-width: 80%; height: 100%; margin: 30px 0px;"></a>
<!-- Slower Example -->
<img alt="population by generation" src="https://www.pewresearch.org/wp-content/uploads/2020/04/FT_20.04.27_GenerationSize_1.png" style="max-width: 80%; margin: 30px 0px;"></a>

For the image that was mine is the profile picture of “Bob McDoucherson”, the fake Facebook profile at the top.

I generated the image using thispersondoesnotexist.com, and then I made it as speedy as possible like this:

  1. I compressed the JPEG file with https://compressjpeg.com/
  2. I converted the JPEG to a WEBP file (which is faster) https://cloudconvert.com/jpeg-to-webp
  3. Took the new WEBP image and compressed it again with https://shrinkme.app/?s=e

Font Speediness

I made a few tweaks to my Google Font link to make it load at the same time as the rest of my website

<!-- Faster Example --><link rel="preload" href="https://fonts.googleapis.com/css2?family=Exo+2:wght@400;700&display=swap" as="style" onload="this.onload=null;this.rel='stylesheet'" /><!-- Slower Example -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Exo+2:wght@400;700&display=swap" rel="stylesheet">

And it seems like the website is pretty speedy! The only thing that really slows down the website is the share buttons on the side.

The Tech

This is not a complicated website. All of the code, all of the HTML, the CSS, and the Javascript from above, fits on a single file that is less than 350 lines long.

There is no database. There are only two files (the home page and the terms page), and two images: the tiny favicon file that creates the little pride flag on the tab of the browser, and the image that shows up when it gets shared on Facebook. And the fonts come from Google, which takes just one line on the file to link to, and the analytics, which is another 9 lines I just have to copy-paste at the top of the file.

So because it is so simple, I decided to host it online using AWS S3 + Cloudfront, where it can sit happily and only cost pennies, even if (fingers crossed) it gets millions of views.

Step 1: I bought the domain through Namecheap.com.

I used their “beast mode” search to find a domain that mixed up the words “pride”, “celebrate”, “why”, “lgbt”, “lgbtq”, “win”, and a few others. WhyPride.com was available so I snatched it up.

Price: ~$8 per year.

Step 2: I created two AWS S3 buckets to host the website.

First, AWS is the brand that Amazon.com has for all of its software/database/tech infrastructure products.

Second, AWS S3 is basically like Dropbox, with four big differences:

  1. It’s not built for people, so it looks like a bad version of Dropbox.
  2. It IS built for programmers and apps, so it is great if the stuff you want to store is for a website or app to access.
  3. Because it’s built for apps and storing a ton of stuff, it’s an insane amount cheaper than something like Dropbox.
  4. S3 also has an option where if you store a file of code, you can tick a box and it will turn the file you uploaded into a website.

So that’s what I used.

I uploaded my single file and my little favicon image to an S3 “Bucket” (basically a folder), and then flicked the switch for “turn this into a website.”

I then created a second bucket with nothing in it into a website, and then said “automatically redirect anyone who visits this empty website to the website from Bucket #1.”

With that done, Amazon generated a crazy-looking URL, but technically the site was there and working!

Price: Less than $0.01 per year for storage. $0 for data transfer (because I use Cloudfront below)

Step 3: I created an SSL Certificate with AWS Certificate Manager

This step was just so I was able to have my website show up as https://whypride.com instead of http://whypride.com (notice the difference between http“s” vs just http).

The “s” just means that the website is encrypted, so sus people can’t steal any information you’re giving the website.

I didn’t NEED to do this because I don’t actually have anything secure I’m doing on the website (remember, it’s just a simple website that doesn’t ask for information or anything…it’s basically a glorified brochure), but I did it because:

  1. If you have the choice to be secure, why not?
  2. I love the “lock” icon that you get in the browser when you visit a secure site

Price: Free

Step 4: I made the website even faster by using the Cloudfront CDN

If you don’t know what a CDN is, a simple metaphor is when you watch spy movies and the spy is away from home base and they are out of weapons, so they go to a “safehouse” they know about and restock.

Since they are a cool spy, they know about the location of hundreds of these safehouses around the world.

CDNs are the lame version of that: it automatically uploads your files (or in my case, my website) to hundreds of different servers around the world so that no matter where the website visitor is from, there is a server so close to them with all the website data that it loads super fast.

So I made a CDN “distribution” for the two buckets: Bucket #1 that had my website file, and bucket #2 that had the empty website that just redirects visitors to bucket #1.

I made it so that whypride.com would go to bucket #1 and www.whypride.com would go to bucket #2. This means that any who goes to the www version of the website will be redirected to the non-www version of the website.

Price:

My website has a size of 176kb, which means that one million website hits would mean I transfer 176GB.

176GB of data * $0.085 per GB of data transferred to web visitors = $14.96

Also, Cloudfront charges $0.0075 per 10,000 requests, so

1,000,000 requests ÷ 10,000 requests * $0.0075 = $0.75

So the combined cost per million visitors is $15.71.

Step 5: I connected the whypride.com website to all of these AWS services using AWS Route 53 and changing the Namecheap nameservers.

AWS Route 53 is basically a traffic director. You connect it to a domain name and it will “route” everyone who hits that domain name to the correct place (in our case, the closest place to our visitor that Cloudfront has stored our website.)

We tell AWS Route 53 that we want to connect it to our Cloudfront “distributions”, and then Route 53 gives us a list of funny-looking URLs we need to copy-paste into our setting for whypride.com on Namecheap.

These Route 53 instructions are all set up in something called a “hosted zone”.

Price:

$0.50 / mo per hosted zone.

$0.40 per million queries.

Or $6.40 total for the year

Our Combined Price

If we keep the website for 1 year and get one million visitors, the combined price is $8 for the domain name + $15.71 for Cloudfront + $6.40 for Route 53 =

$30.11/yr, or $2.51/mo.

And because AWS is built to handle millions of visitors per minute, the chance of my site ever getting overwhelmed with traffic is basically zero. This is a crazy scalable setup at 30% of the price of budget-level hosting.

The Persuasion

The intent of the post is to be informative first, but it has a strong secondary goal of persuading people to be allies.

I talk about how there is research about how when people “come out” that it has a positive effect on LGBTQ+ allyship, but I wanted to implement a few other psychologically persuasive measures into the data.

Inevitability:

This study found evidence that when people feel like things are inevitable, they will shift their opinions to make the inevitable outcome more palatable.

By really highlighting momentum, I hope that readers will feel the tug to re-evaluated their opinions by imagining what the world will look like when they’re in a group of 20 people and the other 19 people would find their views as bigoted.

Peer pressure. It’s real.

Natural & Normal:

The book “The Righteous Mind” talks about how people who lean conservative are more likely to value authority and sanctity, which I can use, because both of those values are shifted based on whatever we decide is “the norm” in society.

In other words, they are “popularity-driven” values.

So showing a wall of flags for the current supporters at the beginning vs interspersing them among the whole grid seemed like a good way to visually show “the norm” that is allyship.

The Art of War: Leave an Outlet

Sun Tzu says in The Art of War that you shouldn’t ever corner an enemy, which makes sense: when people feel like their only option is to fight to the death, then that’s what they’ll do.

By talking about my personal switch, I hint (or in my Instagram video, proclaim), that there is an option for people other than digging in their heels. There won’t be hostages or tribunals… the cost of switching is less than the cost of staying.

Note: Persuasion is Icky?

If this feels too calculated to you, I have to remind you of something:

I loved showing my work in math class. Some of the smarter kids in my class hated it, and loved the feeling of skipping steps with their well-honed intuition.

But not me. There is something about the methodical scaffolding of miniature steps that lead to a greater solution that feels right to me.

And that’s how this is: I find that the people who react most harshly to this type of calculated persuasive thinking aren’t the people who “don’t understand the math”. It’s the people who ARE persuasive who hate that the thing they are so intuitively good at is being dissected al estilo sausage factory.

It’s like explaining why a joke is funny — it doesn’t just kill the joke, but it undermines the joker.

Which is my long way of saying, I’m sorry if this attempt to codify persuasion makes you mad, but I think if you reflect, you might discover the reason it makes you mad is that you’re good at it.

The Promotion

I haven’t started promoting the website yet, but if it goes well, I’ll post an update here on Medium. So follow me here on Medium, or on Instagram or add your email here and I’ll send you an email when it’s published.

And you can always follow me on social media or comment below, especially if you have questions or feedback for improvement.

ExplainGood Instagram

My Instagram

My Twitter

--

--

Tanner Jones

Operations + Marketing @Charisma Hacking, Sporadic Content @ExplainGood