forked from alshedivat/al-folio
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added support for a newsletter (alshedivat#2517)
In reference to idea: alshedivat#2097 In reference to request: alshedivat#923 (comment) Added support to integrate a [loops.so](https://loops.so/) mailing list into the site. To use, you need to enable `newsletter` in `_config.yml`. You also must specify a loops endpoint (although I think any mailing list endpoint can work), which you can get when you set up a mailing list on loops. More documentation on loops: [here](https://loops.so/docs/forms/custom-form). Once that is enabled, the behavior is different depending on how you specified your footer to behave in `_config.yml`. If `footer_fixed: true`, then the sign up will appear at the bottom of the about page, as well as at the bottom of blog posts, if you enable `related_posts`. If `footer_fixed: false`, then the newsletter signup will be in the footer (on every page), like it is in on [my website](https://asboyer.com). I'm not attached to the placement of the signup, and you can choose to include it wherever you want with `{% include scripts/newsletter.liquid %}`. Also if you include positional variables into that, you can choose how you center the signup. So `{% include scripts/newsletter.liquid left=true %}` positions the signup bar to the left. Here are some screenshots below: ## Dark version ![image](https://github.com/alshedivat/al-folio/assets/52665298/af7fdb81-6e5f-47a9-958b-4cb93bba9e8f) ## Light version ![image](https://github.com/alshedivat/al-folio/assets/52665298/927f8bc5-b481-448b-ae5e-6f5b1c613243) I think the input field color should probably change to maybe be light for both themes? What do you think? I think the dark background looks cool, but I don't usually see that done like that on other sites. ## Footer fixed ![image](https://github.com/alshedivat/al-folio/assets/52665298/c52f3dc1-0e45-400e-8b71-eeb00d00cb01) ![image](https://github.com/alshedivat/al-folio/assets/52665298/678a2d45-88ab-4d9a-b8cc-9fc6db26d744) ## Footer not fixed ![image](https://github.com/alshedivat/al-folio/assets/52665298/fd2c0228-2bce-4335-ac3c-5cb20a3307e2) ![image](https://github.com/alshedivat/al-folio/assets/52665298/f594b4f2-67e0-4f2b-a3e8-febd579aaf19) To clarify, if footer isn't fixed, the email signup will appear on every page. --------- Co-authored-by: George <[email protected]>
- Loading branch information
1 parent
5afa8a9
commit b7deeb7
Showing
7 changed files
with
320 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,176 @@ | ||
<div | ||
class="newsletter-form-container" | ||
{% if include.center %} | ||
style="margin: 20px" | ||
{% endif %} | ||
> | ||
<form | ||
class="newsletter-form" | ||
action="https://app.loops.so/api/newsletter-form/{{ site.newsletter.endpoint }}" | ||
method="POST" | ||
style="justify-content: {% if include.left %}flex-start{% elsif include.right %}flex-end{% else %}center{% endif %}" | ||
> | ||
<input | ||
class="newsletter-form-input" | ||
name="newsletter-form-input" | ||
type="email" | ||
placeholder="[email protected]" | ||
required="" | ||
> | ||
|
||
<button | ||
type="submit" | ||
class="newsletter-form-button" | ||
style="justify-content: {% if include.left %}flex-start{% elsif include.right %}flex-end{% else %}center{% endif %}" | ||
> | ||
subscribe | ||
</button> | ||
|
||
<button | ||
type="button" | ||
class="newsletter-loading-button" | ||
style="justify-content: {% if include.left %}flex-start{% elsif include.right %}flex-end{% else %}center{% endif %}" | ||
> | ||
Please wait... | ||
</button> | ||
</form> | ||
|
||
<div | ||
class="newsletter-success" | ||
style="justify-content: {% if include.left %}flex-start{% elsif include.right %}flex-end{% else %}center{% endif %}" | ||
> | ||
<p class="newsletter-success-message">You're subscribed!</p> | ||
</div> | ||
|
||
<div | ||
class="newsletter-error" | ||
style="justify-content: {% if include.left %}flex-start{% elsif include.right %}flex-end{% else %}center{% endif %}" | ||
> | ||
<p class="newsletter-error-message">Oops! Something went wrong, please try again</p> | ||
</div> | ||
|
||
<button | ||
class="newsletter-back-button" | ||
type="button" | ||
onmouseout='this.style.textDecoration="none"' | ||
onmouseover='this.style.textDecoration="underline"' | ||
> | ||
← Back | ||
</button> | ||
</div> | ||
|
||
<script> | ||
function submitHandler(event) { | ||
event.preventDefault(); | ||
var container = event.target.parentNode; | ||
var form = container.querySelector('.newsletter-form'); | ||
var formInput = container.querySelector('.newsletter-form-input'); | ||
var success = container.querySelector('.newsletter-success'); | ||
var errorContainer = container.querySelector('.newsletter-error'); | ||
var errorMessage = container.querySelector('.newsletter-error-message'); | ||
var backButton = container.querySelector('.newsletter-back-button'); | ||
var submitButton = container.querySelector('.newsletter-form-button'); | ||
var loadingButton = container.querySelector('.newsletter-loading-button'); | ||
const rateLimit = () => { | ||
errorContainer.style.display = 'flex'; | ||
errorMessage.innerText = 'Too many signups, please try again in a little while'; | ||
submitButton.style.display = 'none'; | ||
formInput.style.display = 'none'; | ||
backButton.style.display = 'block'; | ||
}; | ||
// Compare current time with time of previous sign up | ||
var time = new Date(); | ||
var timestamp = time.valueOf(); | ||
var previousTimestamp = localStorage.getItem('loops-form-timestamp'); | ||
// If last sign up was less than a minute ago | ||
// display error | ||
if (previousTimestamp && Number(previousTimestamp) + 60000 > timestamp) { | ||
rateLimit(); | ||
return; | ||
} | ||
localStorage.setItem('loops-form-timestamp', timestamp); | ||
submitButton.style.display = 'none'; | ||
loadingButton.style.display = 'flex'; | ||
var formBody = 'userGroup=&email=' + encodeURIComponent(formInput.value); | ||
fetch(event.target.action, { | ||
method: 'POST', | ||
body: formBody, | ||
headers: { | ||
'Content-Type': 'application/x-www-form-urlencoded', | ||
}, | ||
}) | ||
.then((res) => [res.ok, res.json(), res]) | ||
.then(([ok, dataPromise, res]) => { | ||
if (ok) { | ||
// If response successful | ||
// display success | ||
success.style.display = 'flex'; | ||
form.reset(); | ||
} else { | ||
// If response unsuccessful | ||
// display error message or response status | ||
dataPromise.then((data) => { | ||
errorContainer.style.display = 'flex'; | ||
errorMessage.innerText = data.message ? data.message : res.statusText; | ||
}); | ||
} | ||
}) | ||
.catch((error) => { | ||
// check for cloudflare error | ||
if (error.message === 'Failed to fetch') { | ||
rateLimit(); | ||
return; | ||
} | ||
// If error caught | ||
// display error message if available | ||
errorContainer.style.display = 'flex'; | ||
if (error.message) errorMessage.innerText = error.message; | ||
localStorage.setItem('loops-form-timestamp', ''); | ||
}) | ||
.finally(() => { | ||
formInput.style.display = 'none'; | ||
loadingButton.style.display = 'none'; | ||
backButton.style.display = 'block'; | ||
}); | ||
} | ||
function resetFormHandler(event) { | ||
var container = event.target.parentNode; | ||
var formInput = container.querySelector('.newsletter-form-input'); | ||
var success = container.querySelector('.newsletter-success'); | ||
var errorContainer = container.querySelector('.newsletter-error'); | ||
var errorMessage = container.querySelector('.newsletter-error-message'); | ||
var backButton = container.querySelector('.newsletter-back-button'); | ||
var submitButton = container.querySelector('.newsletter-form-button'); | ||
success.style.display = 'none'; | ||
errorContainer.style.display = 'none'; | ||
errorMessage.innerText = 'Oops! Something went wrong, please try again'; | ||
backButton.style.display = 'none'; | ||
formInput.style.display = 'flex'; | ||
submitButton.style.display = 'flex'; | ||
} | ||
var formContainers = document.getElementsByClassName('newsletter-form-container'); | ||
for (var i = 0; i < formContainers.length; i++) { | ||
var formContainer = formContainers[i]; | ||
var handlersAdded = formContainer.classList.contains('newsletter-handlers-added'); | ||
if (handlersAdded) continue; | ||
formContainer.querySelector('.newsletter-form').addEventListener('submit', submitHandler); | ||
formContainer.querySelector('.newsletter-back-button').addEventListener('click', resetFormHandler); | ||
formContainer.classList.add('newsletter-handlers-added'); | ||
} | ||
</script> | ||
|
||
<noscript> | ||
<style> | ||
.newsletter-form-container { | ||
display: none; | ||
} | ||
</style> | ||
</noscript> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters