I was asked by a client to "soft-gate" user emails. The client wanted a list of emails from people using the application, but didn't want to discourage anyone from use. This presented a problem - how could I ask users' for their emails without preventing them from using the app (or pissing them off so much they closed the window)? And how could I remember they had visited and not ask for their email address again?
First things first - this solution is in no way even remotely secure. Devise has a "soft" sign up feature that allows users to start with entering only their email address (and then adding a password later) that you may want to check out if you're looking for real user authentication. In this case I was only trying to amass email addresses for a mailing list.
Question:
How to collect email addresses of users without being too annoying or preventing them from using the app?
Problem:
User state must be saved somehow, because you don't want the app requesting an email address every time the user visits the site.
Solution:
Save a cookie on the user's browser, and read the cookie to determine if the user has already visited the site. If they have, let them through. If they haven't, show a pop-up modal asking for their email address, but allow them to click anywhere on the page to close the modal and still use the site.
Step 1: Save a cookie
In the create
method in the users
controller add
cookies[:user_email] = @user.email
if the user successfully saves.
Step 2: Create a modal
I'm lazy, this is almost directly from the bootstrap docs. My modal view renders my users#new
form. I send in the locals
as User.new
because form_for user
needs a user. Usually this is automagically done for you if the form is accessed via the create
action.:
<!-- Modal -->
<div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">Modal title</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<%= render partial: 'users/form', locals: { user: User.new } %>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
Step 3: Check for a cookie
So, the bootstrap modal is designed to be triggered by a button. This is straight from the docs. I want to trigger it ONLY if the cookie isn't set. This tripped me up at first, I tried accessing cookies[:user_email]
in the view. No dice. The correct way:
In the root
controller index (the homepage) I added this method:
(the index action of the root controller
)
def index
@user_email = cookies[:user_email]
end
Then in the view I checked for my cookie:
layouts/application.html.haml
(or erb whatever you're into)
- if !@user_email
#render-modal
= render 'modals/user_email.html.erb'
So, @user_email
is set in the index
method. If @user_email
does not exist (i.e. the cookie has not been created), I create a div
with an id of render-modal
.
Step 4: Show the modal
Quick jquery snippet to show the modal if the div created above exists:
app/assets/javascripts/modals.js
$(document).ready(function() {
if ($('#render-modal').length) {
$('#myModal').modal({show:true});
}
});
There you have it! A quick way to render a pop-up modal if the user hasn't visited your site before. Now start collecting email addresses and sending great content to your users!
Top comments (0)