Skip to content

Instantly share code, notes, and snippets.

@adriaandotcom
Created September 22, 2020 20:54
Show Gist options
  • Save adriaandotcom/10981ed13f6966ff2666a3ac5874f798 to your computer and use it in GitHub Desktop.
Save adriaandotcom/10981ed13f6966ff2666a3ac5874f798 to your computer and use it in GitHub Desktop.
Sales popup
<!--
Shared because of this Tweet: https://twitter.com/iammarcthomas/status/1308507994334822400
-->
<div
data-sales-vue
v-bind:class="[{ finished: isFinished }, 'sales-popup', 'box']"
>
<a v-if="!isFinished" class="close" v-on:click="onClose">&times;</a>
<h2 v-if="!isFinished">
\{{ heading || (currentQuestion || questions[0]).question }}
</h2>
<p v-if="error" role="alert">\{{ error }}</p>
<div class="finished" v-if="isFinished">
<svg
xmlns="http://www.w3.org/2000/svg"
width="100px"
height="100px"
viewBox="0 0 24 24"
>
<path
fill="var(--primary-color, #ff6600)"
d="M18 1l-6 4-6-4-6 5v7l12 10 12-10v-7z"
/>
</svg>
<p class="mb-0">Thank you</p>
</div>
<ul class="choices" v-else-if="!heading">
<li
v-for="answer in (currentQuestion || questions[0]).answers"
:key="answer.slug"
v-on:click="choose((currentQuestion || questions[0]), answer)"
>
\{{ answer.text }}
</li>
</ul>
<form v-else v-on:submit.prevent="onSubmit">
<input
class="mt-1"
type="email"
placeholder="Enter your email..."
autocomplete="username"
v-model="email"
/>
<input class="button" type="submit" value="Tell me more" />
</form>
</div>
<script>
(function () {
var hideSalesPopup =
IS_ROBOT || getCookie("closed").indexOf("sales-popup") > -1;
if (hideSalesPopup) return;
var localhost = window.location.hostname === "localhost";
var environment = localhost ? "development" : "production";
var script = document.createElement("script");
var isBelowTheFold = false;
var loaded = false;
var src =
"https://assets.simpleanalytics.com/libraries/vue-" +
environment +
"-2.6.10.js";
script.crossorigin = "anonymous";
script.integrity = localhost
? ""
: "sha384-8t+aLluUVnn5SPPG/NbeZCH6TWIvaXIm/gDbutRvtEeElzxxWaZN+G/ZIEdI/f+y";
script.src = src;
script.onload = useVue;
document.body.appendChild(script);
var updateScrollPercentage = function () {
var heightOfWindow = window.innerHeight;
var contentScrolled = window.pageYOffset;
var bodyHeight = document.body.offsetHeight;
var total = bodyHeight - heightOfWindow;
var got = contentScrolled;
var percent = parseInt((got / total) * 100);
if (percent >= 25) {
isBelowTheFold = true;
window.removeEventListener("scroll", updateScrollPercentage, true);
useVue();
}
};
function setClosedCookie() {
var closed = (getCookie("closed") || "")
.split(",")
.filter(function (slug) {
return slug;
});
closed.push("sales-popup");
setCookie("closed", closed.join(","), 7);
}
updateScrollPercentage();
window.addEventListener("scroll", updateScrollPercentage, true);
function useVue() {
if (!isBelowTheFold || typeof Vue === "undefined" || loaded) return;
loaded = true;
var element = document.querySelector("[data-sales-vue]");
var event = function (event) {
if (typeof sa_event === "function") sa_event("sales_popup_" + event);
};
var app = new Vue({
el: element,
data: {
error: null,
isFinished: false,
currentQuestion: null,
heading: null,
email: "",
questions: [
{
slug: "main_reason",
question:
"What is the main reason that brought you to Simple Analytics?",
goTo: "replacing",
answer: null,
answers: [
{
slug: "privacy_laws",
text: "Privacy laws",
},
{
slug: "ethical",
text: "Ethical reasons",
},
{
slug: "cookie_free",
text: "No cookie banner",
},
{
slug: "ease_of_use",
text: "Ease of use",
},
{
slug: "other",
text: "Other",
},
],
},
{
slug: "replacing",
question: "What tool you consider replacing?",
answer: null,
answers: [
{
slug: "google_analytics",
text: "Google Analytics",
},
{
slug: "matomo",
text: "Matomo",
},
{
slug: "clicky",
text: "Clicky",
},
{
slug: "fathom",
text: "Fathom",
},
{
slug: "none",
text: "None",
},
{
slug: "other",
text: "Other",
},
],
},
],
},
methods: {
choose: function (question, answer) {
event("answer");
event("answered_" + question.slug);
question.answer = answer;
var goTo = answer.goTo || question.goTo;
var found = goTo
? this.questions.find(function (item) {
return item.slug === goTo;
})
: null;
if (found) return (this.currentQuestion = found);
this.askEmail();
},
askEmail: function () {
event("ask_email");
var answers = this.questions.reduce(function (object, question) {
object[question.slug] = question.answer;
return object;
}, {});
var reason =
answers.main_reason.slug === "other"
? null
: answers.main_reason.text;
var compares =
answers.replacing.slug === "none"
? null
: answers.replacing.slug === "other"
? "others"
: answers.replacing.text;
var text =
reason && compares
? "Learn how Simple Analytics handles " +
reason.toLowerCase() +
" and compares with " +
compares
: reason
? "Learn how Simple Analytics handles " + reason.toLowerCase()
: compares
? "Learn how Simple Analytics compares with " + compares
: null;
this.heading =
text || "Learn more about how Simple Analytics can help you";
},
onSubmit: function () {
event("submit");
this.error = null;
var answers = this.questions.reduce(function (object, question) {
object[question.slug] = question.answer.slug;
return object;
}, {});
var options = {
email: this.email,
type: "sales-popup",
answers,
};
if (document.referrer) options.referrer = document.referrer;
var context = this;
postJSON("/subscribe", options, function (response) {
if (response.message) context.error = response.message;
else if (response.status < 400) context.isFinished = true;
else context.error = "Oops, something whent wrong";
if (context.isFinished) setClosedCookie();
});
},
onClose: function () {
event("close");
setClosedCookie();
this.isFinished = true;
},
},
mounted: function () {
event("show");
var style = document.getElementById("sales-popup-style");
style.parentNode.removeChild(style);
},
});
}
})();
</script>
<style id="sales-popup-style">
[data-sales-vue] {
display: none;
}
</style>
<style>
@keyframes fadeInUp {
from {
transform: translate3d(0, 100%, 0);
}
to {
transform: translate3d(0, 0, 0);
}
}
.sales-popup {
--background-color: white;
--option-background: var(--background-primary);
--option-background-hover: var(--background-block-alt);
--transform: translateY(0);
position: fixed;
background-color: var(--background-color);
transition: all var(--dark-mode-transition), transform 2s ease-in-out 2s;
width: 320px;
max-width: calc(100% - 3rem);
border: 1px solid var(--border-color);
border-color: var(--border-color);
padding: 2rem;
bottom: 0;
left: 1.5rem;
z-index: 100;
border-radius: 4px 4px 0 0;
animation-name: fadeInUp;
animation-duration: 1s;
color: var(--text-color);
transform: var(--transform);
}
.sales-popup::after {
content: "";
position: absolute;
z-index: -1;
top: 0;
left: 0;
right: 0;
bottom: 0;
border-radius: 4px 4px 0 0;
box-shadow: 0px 0px 10px 5px #20292a;
opacity: 0;
transition: opacity var(--dark-mode-transition);
}
html.dark .sales-popup {
--background-color: var(--background-primary);
--option-background: var(--background-secondary);
--option-background-hover: var(--background-block-alt);
}
html.dark .sales-popup::after {
opacity: 1;
}
.sales-popup.finished {
--transform: translateY(120%);
}
.sales-popup .close {
position: absolute;
display: block;
top: 0rem;
right: 0.2rem;
padding: 0.5rem;
line-height: 1;
font-size: 20px;
color: var(--icon-color);
}
.sales-popup h2 {
font-size: 16px !important;
margin: 0 !important;
}
.sales-popup .choices {
list-style-type: none;
padding: 0;
margin: 1rem 0 0 0;
}
.sales-popup .choices li {
margin: 0 0 0.5rem 0;
padding: 0.2rem 0;
display: block;
transition: all var(--dark-mode-transition);
cursor: pointer;
background-color: var(--option-background);
}
.sales-popup .choices li:last-of-type {
margin-bottom: 0;
}
.sales-popup .choices li:hover {
background-color: var(--option-background-hover);
}
</style>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment