Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Update standard-js snippet to handle geolocated snippets.

Geolocated snippets have an extra data attribute, data-country, that
determines which country they should be available to. The JS should
use the geolocation service at geo.mozilla.org to determine the user's
country, and include snippets targeted at that country in the set of
possible snippets.

To avoid excessive traffic, we cache the user's country in localStorage
for 30 days. In addition, we only download the user's country AFTER
snippets are displayed; the geolocated snippets will show up next time
the user hits about:home, and we avoid any delay in showing a snippet
if the geolocation service is down.
  • Loading branch information...
commit 29aff014bbe4f8b66b5e18d126eeb80032407de1 1 parent 3e15635
@Osmose Osmose authored
Showing with 88 additions and 1 deletion.
  1. +88 −1 standard-js/snippet.html
View
89 standard-js/snippet.html
@@ -1,9 +1,19 @@
<script type="text/javascript">
//<![CDATA[
+/*!
+ * $script.js Async loader & dependency manager
+ * https://github.com/ded/script.js
+ * (c) Dustin Diaz, Jacob Thornton 2011
+ * License: MIT
+ */
+(function(a,b,c){typeof c["module"]!="undefined"&&c.module.exports?c.module.exports=b():typeof c["define"]!="undefined"&&c["define"]=="function"&&c.define.amd?define(a,b):c[a]=b()})("$script",function(){function p(a,b){for(var c=0,d=a.length;c<d;++c)if(!b(a[c]))return j;return 1}function q(a,b){p(a,function(a){return!b(a)})}function r(a,b,i){function o(a){return a.call?a():d[a]}function t(){if(!--n){d[m]=1,l&&l();for(var a in f)p(a.split("|"),o)&&!q(f[a],o)&&(f[a]=[])}}a=a[k]?a:[a];var j=b&&b.call,l=j?b:i,m=j?a.join(""):b,n=a.length;return setTimeout(function(){q(a,function(a){if(h[a])return m&&(e[m]=1),h[a]==2&&t();h[a]=1,m&&(e[m]=1),s(!c.test(a)&&g?g+a+".js":a,t)})},0),r}function s(c,d){var e=a.createElement("script"),f=j;e.onload=e.onerror=e[o]=function(){if(e[m]&&!/^c|loade/.test(e[m])||f)return;e.onload=e[o]=null,f=1,h[c]=2,d()},e.async=1,e.src=c,b.insertBefore(e,b.firstChild)}var a=document,b=a.getElementsByTagName("head")[0],c=/^https?:\/\//,d={},e={},f={},g,h={},i="string",j=!1,k="push",l="DOMContentLoaded",m="readyState",n="addEventListener",o="onreadystatechange";return!a[m]&&a[n]&&(a[n](l,function t(){a.removeEventListener(l,t,j),a[m]="complete"},j),a[m]="loading"),r.get=s,r.order=function(a,b,c){(function d(e){e=a.shift(),a.length?r(e,d):r(e,b,c)})()},r.path=function(a){g=a},r.ready=function(a,b,c){a=a[k]?a:[a];var e=[];return!q(a,function(a){d[a]||e[k](a)})&&p(a,function(a){return d[a]})?b():!function(a){f[a]=f[a]||[],f[a][k](b),c&&c(e)}(a.join("|")),r},r},this);
+
(function(showDefaultSnippets) {
var SAMPLE_RATE = 0.1;
var STATS_URL = 'https://snippets-stats.mozilla.org/foo.html';
+ var GEO_URL = 'http://geo.mozilla.org/country.js';
+ var GEO_CACHE_DURATION = 1000 * 60 * 60 * 24 * 30; // 30 days
// showDefaultSnippets polyfill, available in about:home v4
if (typeof showDefaultSnippets !== 'function') {
@@ -16,7 +26,7 @@
var snippets = (document.getElementById('snippetContainer')
.getElementsByClassName('snippet'));
if (snippets.length > 0) {
- var show_snippet = snippets[Math.floor(Math.random() * snippets.length)];
+ var show_snippet = chooseSnippet(snippets);
show_snippet.style.display = 'block';
try {
@@ -39,10 +49,87 @@
var parameters = ('sample_rate=' + SAMPLE_RATE + '&snippet_name=' +
show_snippet_id);
modifyLinks(show_snippet.getElementsByTagName('a'), parameters);
+
+ // Fetch user country if we don't have it.
+ // We have to do this at the end because I couldn't find a JavaScript
+ // loader that doesn't block the JS that triggered loading, and don't
+ // have the time to implement it myself. Guess "async loader" doesn't
+ // mean what I thought it meant.
+ if (!haveUserCountry()) {
+ downloadUserCountry();
+ }
} else {
showDefaultSnippets();
}
+ // Choose which snippet to display to the user based on various factors,
+ // such as which country they are in.
+ function chooseSnippet(snippets) {
+ // Build an object that maps countries to snippets.
+ var snippetsFor = {};
+ for (var k = 0; k < snippets.length; k++) {
+ var snippet = snippets[k];
+ var country = snippet.parentNode.dataset.country || 'none';
+
+ // Create a new entry in the object if it doesn't exist.
+ if (snippetsFor.hasOwnProperty(country)) {
+ snippetsFor[country].push(snippet);
+ } else {
+ snippetsFor[country] = [snippet];
+ }
+ }
+
+ // Choose a random snippet from the set of non-geolocated snippets,
+ // including snippets for the user's country if it is available.
+ var country = getUserCountry();
+ if (country && snippetsFor.hasOwnProperty(country)) {
+ snippets = snippetsFor[country].concat(snippetsFor.none);
+ } else {
+ snippets = snippetsFor.none;
+ }
+ return snippets[Math.floor(Math.random() * snippets.length)];
+ }
+
+ // Check whether we have the user's country stored and if it is still valid.
+ function haveUserCountry() {
+ // Check if there's an existing country code to use.
+ if (localStorage.geoCountry) {
+ // Make sure we have a valid lastUpdated date.
+ var lastUpdated = Date.parse(localStorage.geoLastUpdated);
+ if (lastUpdated) {
+ // Make sure that it is past the lastUpdated date.
+ var now = new Date();
+ if (now < lastUpdated + GEO_CACHE_DURATION) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+
+ function getUserCountry() {
+ if (haveUserCountry()) {
+ return localStorage.geoCountry.toLowerCase();
+ } else {
+ return null;
+ }
+ }
+
+ // Download the user's country using the geolocation service.
+ function downloadUserCountry() {
+ $script(GEO_URL, 'geo');
+ $script.ready('geo', function() {
+ try {
+ localStorage.geoCountry = geoip_country_code();
+ localStorage.geoLastUpdated = new Date();
+ } catch(e) {
+ // Most likely failed to load JS file. Continue on without us,
+ // we'll try again next time.
+ }
+ });
+ }
+
// Notifies stats server that the given snippet ID
// was shown. No personally-identifiable information
// is sent.
Please sign in to comment.
Something went wrong with that request. Please try again.