Skip to content

Commit

Permalink
Merge pull request #994 from dpoirier/bug-780935-track-newsletter-sig…
Browse files Browse the repository at this point in the history
…nups

Bug 780935: Track newsletter signups in Google Analytics
  • Loading branch information
alexgibson committed Jul 18, 2013
2 parents df461a6 + 969508a commit 36b4ffb
Show file tree
Hide file tree
Showing 9 changed files with 141 additions and 31 deletions.
2 changes: 1 addition & 1 deletion bedrock/base/templates/macros.html
Expand Up @@ -28,7 +28,7 @@
</div>
{% endif %}

<form class="billboard{% if request.newsletter_form.errors %} has-errors{% endif %}"
<form class="billboard newsletter-form{% if request.newsletter_form.errors %} has-errors{% endif %}"
{% if footer %}
id="footer-email-form" action="#footer-email-form"
{% else %}
Expand Down
4 changes: 3 additions & 1 deletion bedrock/mozorg/templates/mozorg/base-resp.html
Expand Up @@ -7,7 +7,9 @@
{% block body_class %}sand lang-{{ LANG }}{% endblock %}

{% block email_form %}
<form class="billboard" id="footer-email-form" method="post"
{# Note: not using the email footer macro here because that submits the
subscription to Bedrock. This form goes to sendto.mozilla.org #}
<form class="billboard newsletter-form" id="footer-email-form" method="post"
action="https://sendto.mozilla.org/page/s/sign-up-for-mozilla">
<h3>Get Mozilla updates</h3>

Expand Down
9 changes: 7 additions & 2 deletions bedrock/newsletter/templates/newsletter/existing.html
Expand Up @@ -22,7 +22,8 @@ <h1>{{ _('Manage your <span>Newsletter Subscriptions</span>') }}</h1>
{% endif %}

{% if formset %}
<form method="post" action="" id="existing-newsletter-form" class="container billboard">
<form method="post" action="" id="existing-newsletter-form" class="container billboard"
data-initial-newsletters='{{ newsletters_subscribed }}'>
{{ formset.management_form }}

<div id="basic-settings">
Expand Down Expand Up @@ -109,10 +110,14 @@ <h4 class="title">
</div>

<div class="field submit-field">
<input name="submit" type="submit" value="Save Preferences" class="button">
<input type="submit" value="Save Preferences" class="button">
</div><!-- close .submit-field -->

</form>
{% endif %}
<!-- End content -->
{% endblock %}

{% block js %}
{{ js('existing') }}
{% endblock js %}
3 changes: 3 additions & 0 deletions bedrock/settings/base.py
Expand Up @@ -377,6 +377,9 @@ def JINJA_CONFIG():
'js/mozorg/contribute-university-ambassadors.js',
'js/base/mozilla-input-placeholder.js',
),
'existing': (
'js/newsletter/existing.js',
),
'expanders': (
'js/base/mozilla-expanders.js',
),
Expand Down
45 changes: 45 additions & 0 deletions media/js/base/footer-email-form.js
Expand Up @@ -27,4 +27,49 @@ $(document).ready(function() {
}
});

// reallly primative validation e.g a@a
// matches built-in validation in Firefox
function validateEmail(elementValue) {
var emailPattern = /\S+@\S+/;
return emailPattern.test(elementValue);
}

function validateForm($form) {
var email = $('#id_email').val();
var $privacy = $('#id_privacy');

return validateEmail(email) && $privacy.is(':checked');
}

$('.newsletter-form').submit(function (e) {
var $form = $(this);

// If the browser has native validation, we know the input is valid
// because this submit handler won't even be invoked until the input
// validates.
if (('checkValidity' in $form) || validateForm($form)) {

// If there's a name=newsletter input field, we can get the newsletter
// from that. If not, assume we've got one of the forms that subscribes
// to the foundation newsletter.
var $input = $form.children('input[name=newsletter]');
var newsletter;
if ($input.length === 0) {
newsletter = "Registered for Firefox Updates";
} else {
newsletter = $input.val();
}

if (gaTrack && newsletter !== '') {
// Need to wait to submit, until after we're sure we've sent
// the tracking event to GA.
e.preventDefault();
$form.unbind('submit');
gaTrack([['_trackEvent', 'Newsletter Registration', 'submit', newsletter]],
function () { $form.submit(); }
);
}
}
// Else, just let the form submit.
});
});
51 changes: 50 additions & 1 deletion media/js/base/global.js
Expand Up @@ -95,7 +95,7 @@ function isFirefoxUpToDate(latest, esr) {
} else {
latestFirefoxVersion = parseInt(latest.split('.')[0], 10);
}

return ($.inArray(fx_version, esrFirefoxVersions) !== -1 ||
latestFirefoxVersion <= fx_version);
}
Expand All @@ -116,3 +116,52 @@ var $strings = $('#strings');
window.trans = function trans(stringId) {
return $strings.data(stringId);
};


function gaTrack(eventsArray, callback) {
// submit eventsArray to GA and call callback only after they've
// been sent, or if sending fails.
// Example usage:
//
// $(function() {
// var handler = function(e) {
// var _this = this;
// e.preventDefault();
// $(_this).off('submit', handler);
// gaTrack(
// [['_trackEvent', 'Newsletter Registration', 'submit', newsletter]],
// function() {$(_this).submit();}
// );
// };
// $(thing).on('submit', handler);
// });

var timer = null;
var hasCallback = typeof(callback) === 'function';
var gaCallback = function() {
clearTimeout(timer);
if (hasCallback) {
callback();
}
}
if (typeof(window._gaq) === 'object') {
// Failsafe - be sure we do the callback in a half-second
// even if GA isn't able to send in our trackEvent.
timer = setTimeout(gaCallback, 500);
// But ordinarily, we get GA to call us back immediately after
// it finishes sending our things.
window._gaq.push(
// https://developers.google.com/analytics/devguides/collection/analyticsjs/advanced#hitCallback
// This is called AFTER GA has sent all pending data:
['_set', 'hitCallback', gaCallback()]
)
// send events to GA
window._gaq.push.apply(this, eventsArray);
} else {
// GA disabled or blocked or something, make sure we still
// call the caller's callback:
if (hasCallback) {
callback();
}
}
}
13 changes: 0 additions & 13 deletions media/js/firefox/firstrun/common.js
Expand Up @@ -93,17 +93,4 @@
video_closing = false;
}
});

$('#footer_email_submit').on('click', function(e) {
// if form is valid, delay submission to wait for GA tracking
if ($('#footer-email-form')[0].checkValidity()) {
e.preventDefault();

gaq_track("Newsletter Registration", "submit", "Registered for Firefox Updates");

setTimeout(function() {
$('#footer-email-form').submit();
}, 500);
}
});
})(window.jQuery);
13 changes: 0 additions & 13 deletions media/js/firefox/firstrun/firstrun.js
Expand Up @@ -19,17 +19,4 @@

gaq_track('first run interaction', action, 'First Run Video');
});

$('#footer_email_submit').on('click', function(e) {
// if form is valid, delay submission to wait for GA tracking
if ($('#footer-email-form')[0].checkValidity()) {
e.preventDefault();

gaq_track("Newsletter Registration", "submit", "Registered for Firefox Updates");

setTimeout(function() {
$('#footer-email-form').submit();
}, 500);
}
});
})(window.jQuery);
32 changes: 32 additions & 0 deletions media/js/newsletter/existing.js
@@ -0,0 +1,32 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

// Tell GA if user subscribed to anything new
jQuery(function($) {
var handler = function (e) {
e.preventDefault();
var $form = $(this);
$form.unbind('submit', handler);

// get the newsletters they're already subscribed to
// from the form's data-initial-newsletters attribute.
var initialNewsletters = $form.data('initialNewsletters');
var events = [];
$form.find('input[name^="form-"][name$="-subscribed"]:checked').each(function () {
var newsletterInputName = $(this).attr('name').replace("-subscribed", "-newsletter");
var newsletter = $("input[name='" + newsletterInputName + "']").val();
if (initialNewsletters.indexOf(newsletter) === -1) {
// newly subscribed to this newsletter
events.push(['_trackEvent', 'Newsletter Registration', 'submit', newsletter]);
}
});
if (gaTrack && events.length > 0) {
gaTrack(events, function () { $form.submit(); });
} else {
$form.submit();
}
};

$('form#existing-newsletter-form').on('submit', handler);
});

0 comments on commit 36b4ffb

Please sign in to comment.