Skip to content

Instantly share code, notes, and snippets.

@FokkeZB
Last active December 16, 2015 16:49
Show Gist options
  • Select an option

  • Save FokkeZB/5466012 to your computer and use it in GitHub Desktop.

Select an option

Save FokkeZB/5466012 to your computer and use it in GitHub Desktop.

Revisions

  1. FokkeZB revised this gist Oct 2, 2013. 2 changed files with 2 additions and 222 deletions.
    2 changes: 1 addition & 1 deletion RATING.md
    Original file line number Diff line number Diff line change
    @@ -1,3 +1,3 @@
    # Rate my app

    Information: http://fokkezb.nl/2013/05/23/rate-my-app/
    Moved to: https://github.com/FokkeZB/UTiL/tree/master/rate
    222 changes: 1 addition & 221 deletions rate.js
    Original file line number Diff line number Diff line change
    @@ -1,221 +1 @@
    var _properties = {}, _platform;

    function plus(_points, _show) {

    if (typeof _points !== 'number') {
    _points = 1;
    }

    return _trigger(_points, _show);
    }

    function test() {
    return _trigger();
    }

    function ask() {

    if (typeof _platform !== 'string') {
    _platform = Ti.Platform.name;
    }

    if (_platform === 'iPhone OS' && !exports.appleId) {

    _lookup(function(result) {

    if (!result) {
    Ti.API.debug('[RATE] Lookup failed.');
    return;
    }

    exports.appleId = result.trackId;

    return ask();
    });

    return;
    }

    var buttonNames = [exports.yes, exports.later, exports.never];
    var cancel = buttonNames.length - 1;

    var alertDialog = Titanium.UI.createAlertDialog({
    title: exports.title,
    message: exports.message,
    buttonNames: buttonNames,
    cancel: cancel
    });

    alertDialog.addEventListener('click', function(e) {

    if (buttonNames[e.index] === exports.yes) {
    Ti.App.Properties.setString('rate_done', Ti.App.version);

    open();

    } else if (buttonNames[e.index] === exports.never) {
    Ti.App.Properties.setBool('rate_never', true);
    }

    return;
    });

    alertDialog.show();

    return;
    }

    function open() {

    if (Ti.Platform.name === 'android') {
    Ti.Platform.openURL('market://details?id=' + Ti.App.id);

    } else if (Ti.Platform.name === 'iPhone OS') {

    if (!exports.appleId) {
    _lookup(function(result) {

    if (!result) {
    Ti.API.debug('[RATE] Lookup failed.');
    return;
    }

    exports.appleId = result.trackId;
    return open();
    });

    return;
    }

    Ti.Platform.openURL('itms-apps://itunes.apple.com/WebObjects/MZStore.woa/wa/viewContentsUserReviews?id=' + exports.appleId + '&onlyLatestVersion=true&pageNumber=0&sortOrdering=1&type=Purple+Software');
    }

    return;
    }

    function reset() {
    Ti.API.debug('[RATE] Reset.');

    Ti.App.Properties.removeProperty('rate_done');
    Ti.App.Properties.removeProperty('rate_never');
    Ti.App.Properties.removeProperty('rate_points');
    Ti.App.Properties.removeProperty('rate_asked');

    return;
    }

    function _trigger(_points, _show) {

    if (Ti.App.Properties.getBool('rate_never', false) === true) {
    Ti.API.debug('[RATE] Rating disabled by user.');
    return;
    }

    var rate_done = Ti.App.Properties.getString('rate_done');

    if (exports.eachVersion ? (rate_done === Ti.App.version) : rate_done) {
    Ti.API.debug('[RATE] Rating already done.');
    return;
    }

    var points = Ti.App.Properties.getInt('rate_points', 0);

    if (_points) {
    points = points + (_points || 1);
    Ti.API.debug('[RATE] Rating points changed to: ' + points);
    }

    var now = (new Date() / 1000),
    checked = Ti.App.Properties.getInt('rate_asked', 0);

    if (_show !== false) {

    if (checked === 0) {
    Ti.App.Properties.setInt('rate_asked', now);
    }

    if (points < exports.pointsBetween) {
    Ti.API.debug('[RATE] Not enough points: ' + points + ' of ' + exports.pointsBetween);
    _show = false;

    } else if (checked === 0 || (now - checked) < (exports.daysBetween * 86400)) {
    Ti.API.debug('[RATE] Not enough days' + (checked ? (': ' + Math.round((now - checked) / 86400) + ' of ' + exports.daysBetween) : ''));
    _show = false;
    }
    }

    if (_show !== false) {
    Ti.API.debug('[RATE] Rating triggered!');

    Ti.App.Properties.setInt('rate_points', 0);
    Ti.App.Properties.setInt('rate_asked', now);

    ask();

    } else {
    Ti.App.Properties.setInt('rate_points', points);
    }

    return;
    }

    function _lookup(_callback) {
    var xhr = Ti.Network.createHTTPClient({
    onload: function(e) {
    if (xhr.status === 200 && this.responseText) {
    try {
    var json = JSON.parse(this.responseText);

    if (json.resultCount === 1) {
    _callback(json.results[0]);
    return;

    } else {
    Ti.API.error('[RATE] LOOKUP ERROR ' + this.responseText);
    }

    } catch (err) {
    Ti.API.error('[RATE] LOOKUP ERROR ' + JSON.stringify(err));
    }
    }

    _callback();
    return;
    },
    onerror: function(e) {
    Ti.API.error('[RATE] LOOKUP ERROR ' + JSON.stringify(e.error));
    _callback();
    return;
    }
    });

    var url = 'http://itunes.apple.com/lookup?';

    if (exports.appleId) {
    url = url + 'id=' + exports.appleId;
    } else {
    url = url + 'bundleId=' + Ti.App.id;
    }

    xhr.open('GET', url);
    xhr.send();

    return;
    }

    exports.title = 'Like our app?';
    exports.message = 'Please take a minute to rate it:';
    exports.yes = 'Yes, of course';
    exports.later = 'Ask me later';
    exports.never = 'No, thank you';

    exports.appleId = null;
    exports.daysBetween = 3;
    exports.pointsBetween = 3;
    exports.eachVersion = false;

    exports.plus = plus;
    exports.test = test;
    exports.ask = ask;
    exports.open = open;
    exports.reset = reset;
    // Check https://github.com/FokkeZB/UTiL/tree/master/rate
  2. FokkeZB revised this gist Aug 16, 2013. 1 changed file with 63 additions and 59 deletions.
    122 changes: 63 additions & 59 deletions rate.js
    Original file line number Diff line number Diff line change
    @@ -1,11 +1,11 @@
    var _properties = {}, _platform;

    function plus(_points, _show) {

    if (typeof _points !== 'number') {
    _points = 1;
    }

    return _trigger(_points, _show);
    }

    @@ -14,93 +14,93 @@ function test() {
    }

    function ask() {

    if (typeof _platform !== 'string') {
    _platform = Ti.Platform.name;
    _platform = Ti.Platform.name;
    }

    if (_platform === 'iPhone OS' && !exports.appleId) {
    _lookup(function (result) {

    _lookup(function(result) {

    if (!result) {
    Ti.API.debug('[RATE] Lookup failed.');
    return;
    }

    exports.appleId = result.trackId;

    return ask();
    });

    return;
    }

    var buttonNames = [exports.yes, exports.later, exports.never];
    var cancel = buttonNames.length - 1;

    var alertDialog = Titanium.UI.createAlertDialog({
    title: exports.title,
    message: exports.message,
    buttonNames: buttonNames,
    cancel: cancel
    });

    alertDialog.addEventListener('click', function(e) {

    if (buttonNames[e.index] === exports.yes) {
    Ti.App.Properties.setString('rate_done', Ti.App.version);

    open();

    } else if (buttonNames[e.index] === exports.never) {
    Ti.App.Properties.setBool('rate_never', true);
    }

    return;
    });

    alertDialog.show();

    return;
    }

    function open() {

    if (Ti.Platform.name === 'android') {
    Ti.Platform.openURL('market://details?id=' + Ti.App.id);

    } else if (Ti.Platform.name === 'iPhone OS') {

    if (!exports.appleId) {
    _lookup(function (result) {
    _lookup(function(result) {

    if (!result) {
    Ti.API.debug('[RATE] Lookup failed.');
    return;
    }

    exports.appleId = result.trackId;
    return open();
    });

    return;
    }

    Ti.Platform.openURL('itms-apps://itunes.apple.com/WebObjects/MZStore.woa/wa/viewContentsUserReviews?id=' + exports.appleId + '&onlyLatestVersion=true&pageNumber=0&sortOrdering=1&type=Purple+Software');
    }

    return;
    }

    function reset() {
    Ti.API.debug('[RATE] Reset.');

    Ti.App.Properties.removeProperty('rate_done');
    Ti.App.Properties.removeProperty('rate_never');
    Ti.App.Properties.removeProperty('rate_points');
    Ti.App.Properties.removeProperty('rate_asked');

    return;
    }

    @@ -110,83 +110,87 @@ function _trigger(_points, _show) {
    Ti.API.debug('[RATE] Rating disabled by user.');
    return;
    }

    var rate_done = Ti.App.Properties.getString('rate_done');

    if (exports.eachVersion ? (rate_done === Ti.App.version) : rate_done) {
    Ti.API.debug('[RATE] Rating already done.');
    return;
    }

    var points = Ti.App.Properties.getInt('rate_points', 0);

    if (_points) {
    points = points + (_points || 1);
    Ti.API.debug('[RATE] Rating points changed to: ' + points);
    }

    var now = (new Date() / 1000),
    checked = Ti.App.Properties.getInt('rate_asked', 0);

    if (_show !== false) {

    if (points < exports.pointsBetween) {
    Ti.API.debug('[RATE] Not enough points: ' + points + ' of ' + exports.pointsBetween);
    _show = false;

    } else if (checked === 0 || (now - checked) < (exports.daysBetween * 86400)) {
    Ti.API.debug('[RATE] Not enough days: ' + Math.round((now - checked) / 86400) + ' of ' + exports.daysBetween);
    _show = false;
    }
    }

    if (_show !== false) {

    if (checked === 0) {
    Ti.App.Properties.setInt('rate_asked', now);
    }

    if (points < exports.pointsBetween) {
    Ti.API.debug('[RATE] Not enough points: ' + points + ' of ' + exports.pointsBetween);
    _show = false;

    } else if (checked === 0 || (now - checked) < (exports.daysBetween * 86400)) {
    Ti.API.debug('[RATE] Not enough days' + (checked ? (': ' + Math.round((now - checked) / 86400) + ' of ' + exports.daysBetween) : ''));
    _show = false;
    }
    }

    if (_show !== false) {
    Ti.API.debug('[RATE] Rating triggered!');

    Ti.App.Properties.setInt('rate_points', 0);
    Ti.App.Properties.setInt('rate_asked', now);

    ask();

    } else {
    Ti.App.Properties.setInt('rate_points', points);
    }

    return;
    }

    function _lookup(_callback) {
    var xhr = Ti.Network.createHTTPClient({
    onload: function (e) {
    onload: function(e) {
    if (xhr.status === 200 && this.responseText) {
    try {
    var json = JSON.parse(this.responseText);

    if (json.resultCount === 1) {
    _callback(json.results[0]);
    return;

    } else {
    Ti.API.error('[RATE] LOOKUP ERROR ' + this.responseText);
    }

    } catch (err) {
    Ti.API.error('[RATE] LOOKUP ERROR ' + JSON.stringify(err));
    }
    }

    _callback();
    return;
    },
    onerror: function (e) {
    onerror: function(e) {
    Ti.API.error('[RATE] LOOKUP ERROR ' + JSON.stringify(e.error));
    _callback();
    return;
    }
    });

    var url = 'http://itunes.apple.com/lookup?';

    if (exports.appleId) {
    url = url + 'id=' + exports.appleId;
    } else {
    @@ -195,7 +199,7 @@ function _lookup(_callback) {

    xhr.open('GET', url);
    xhr.send();

    return;
    }

  3. FokkeZB revised this gist May 29, 2013. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion rate.js
    Original file line number Diff line number Diff line change
    @@ -134,7 +134,7 @@ function _trigger(_points, _show) {
    Ti.API.debug('[RATE] Not enough points: ' + points + ' of ' + exports.pointsBetween);
    _show = false;

    } else if (checked === 0 || (now - checked) < (exports.daysBetween * 1)){//86400)) {
    } else if (checked === 0 || (now - checked) < (exports.daysBetween * 86400)) {
    Ti.API.debug('[RATE] Not enough days: ' + Math.round((now - checked) / 86400) + ' of ' + exports.daysBetween);
    _show = false;
    }
  4. FokkeZB revised this gist May 23, 2013. 1 changed file with 2 additions and 0 deletions.
    2 changes: 2 additions & 0 deletions RATING.md
    Original file line number Diff line number Diff line change
    @@ -1 +1,3 @@
    # Rate my app

    Information: http://fokkezb.nl/2013/05/23/rate-my-app/
  5. FokkeZB revised this gist May 23, 2013. 3 changed files with 1 addition and 41 deletions.
    10 changes: 1 addition & 9 deletions RATING.md
    Original file line number Diff line number Diff line change
    @@ -1,9 +1 @@
    I wanted a intelligent library that pops the "Rate my app" question at the right time and is easy to set-up.

    Well, this library at minimum requires no configuration at all and takes just a single line of code, because it reads your app's (bundle) ID from `Ti.App.id` and looks up the App Store ID itself:

    `require('rate').plus();`

    Check out `advanced.js` for all available options.

    I personally like to add points at places where the user has positive interaction with the app, but wait to pop the question until he/she is finished doing that.
    Information: http://fokkezb.nl/2013/05/23/rate-my-app/
    31 changes: 0 additions & 31 deletions advanced.js
    Original file line number Diff line number Diff line change
    @@ -1,31 +0,0 @@
    var rate = require('rate');

    // Set texts
    rate.title = 'Pleeeeease rate!';
    rate.message = 'I would be so thankful!';
    rate.yes = 'Fine';
    rate.later = 'Maybe later';
    rate.never = 'Forget it';

    // Set triggers
    rate.pointsBetween = 100; // Reach 100 points before asking and between each repeat
    rate.daysBetween = 10; // Wait 10 days before asking and between each repeat
    rate.eachVersion = true; // Ask again each new version (unless user chose 'never')

    // Set Apple ID of the app (found in iTunes Connect) manually instead of using the lookup
    rate.appleId = 123456;

    // Reset counts (WARNING: Will also reset the user's wish to never be asked again!)
    rate.reset();

    // Add 1 point and test if we should ask
    rate.plus();

    // Add more points and do not test
    rate.plus(5, false);

    // Just test
    rate.test();

    // Just ask
    rate.show();
    1 change: 0 additions & 1 deletion simple.js
    Original file line number Diff line number Diff line change
    @@ -1 +0,0 @@
    require('rate').plus();
  6. FokkeZB revised this gist May 23, 2013. 2 changed files with 12 additions and 12 deletions.
    4 changes: 2 additions & 2 deletions advanced.js
    Original file line number Diff line number Diff line change
    @@ -12,8 +12,8 @@ rate.pointsBetween = 100; // Reach 100 points before asking and between each rep
    rate.daysBetween = 10; // Wait 10 days before asking and between each repeat
    rate.eachVersion = true; // Ask again each new version (unless user chose 'never')

    // Set iTunes Track ID manually
    rate.iTunesTrackId = 123456;
    // Set Apple ID of the app (found in iTunes Connect) manually instead of using the lookup
    rate.appleId = 123456;

    // Reset counts (WARNING: Will also reset the user's wish to never be asked again!)
    rate.reset();
    20 changes: 10 additions & 10 deletions rate.js
    Original file line number Diff line number Diff line change
    @@ -19,7 +19,7 @@ function ask() {
    _platform = Ti.Platform.name;
    }

    if (_platform === 'iPhone OS' && !exports.iTunesTrackId) {
    if (_platform === 'iPhone OS' && !exports.appleId) {

    _lookup(function (result) {

    @@ -28,7 +28,7 @@ function ask() {
    return;
    }

    exports.iTunesTrackId = result.trackId;
    exports.appleId = result.trackId;

    return ask();
    });
    @@ -72,22 +72,22 @@ function open() {

    } else if (Ti.Platform.name === 'iPhone OS') {

    if (!exports.iTunesTrackId) {
    if (!exports.appleId) {
    _lookup(function (result) {

    if (!result) {
    Ti.API.debug('[RATE] Lookup failed.');
    return;
    }

    exports.iTunesTrackId = result.trackId;
    exports.appleId = result.trackId;
    return open();
    });

    return;
    }

    Ti.Platform.openURL('itms-apps://itunes.apple.com/WebObjects/MZStore.woa/wa/viewContentsUserReviews?id=' + exports.iTunesTrackId + '&onlyLatestVersion=true&pageNumber=0&sortOrdering=1&type=Purple+Software');
    Ti.Platform.openURL('itms-apps://itunes.apple.com/WebObjects/MZStore.woa/wa/viewContentsUserReviews?id=' + exports.appleId + '&onlyLatestVersion=true&pageNumber=0&sortOrdering=1&type=Purple+Software');
    }

    return;
    @@ -129,12 +129,12 @@ function _trigger(_points, _show) {
    checked = Ti.App.Properties.getInt('rate_asked', 0);

    if (_show !== false) {
    if (points < exports.pointsBetween) {
    Ti.API.debug('[RATE] Not enough points: ' + points + ' of ' + exports.pointsBetween);
    _show = false;

    } else if (checked === 0 || (now - checked) < (exports.daysBetween * 86400)) {
    } else if (checked === 0 || (now - checked) < (exports.daysBetween * 1)){//86400)) {
    Ti.API.debug('[RATE] Not enough days: ' + Math.round((now - checked) / 86400) + ' of ' + exports.daysBetween);
    _show = false;
    }
    @@ -187,8 +187,8 @@ function _lookup(_callback) {

    var url = 'http://itunes.apple.com/lookup?';

    if (exports.iTunesTrackId) {
    url = url + 'id=' + exports.iTunesTrackId;
    if (exports.appleId) {
    url = url + 'id=' + exports.appleId;
    } else {
    url = url + 'bundleId=' + Ti.App.id;
    }
    @@ -205,7 +205,7 @@ exports.yes = 'Yes, of course';
    exports.later = 'Ask me later';
    exports.never = 'No, thank you';

    exports.iTunesTrackId = null;
    exports.appleId = null;
    exports.daysBetween = 3;
    exports.pointsBetween = 3;
    exports.eachVersion = false;
  7. FokkeZB revised this gist May 23, 2013. 1 changed file with 1 addition and 0 deletions.
    1 change: 1 addition & 0 deletions advanced.js
    Original file line number Diff line number Diff line change
    @@ -10,6 +10,7 @@ rate.never = 'Forget it';
    // Set triggers
    rate.pointsBetween = 100; // Reach 100 points before asking and between each repeat
    rate.daysBetween = 10; // Wait 10 days before asking and between each repeat
    rate.eachVersion = true; // Ask again each new version (unless user chose 'never')

    // Set iTunes Track ID manually
    rate.iTunesTrackId = 123456;
  8. FokkeZB revised this gist May 23, 2013. 1 changed file with 32 additions and 12 deletions.
    44 changes: 32 additions & 12 deletions rate.js
    Original file line number Diff line number Diff line change
    @@ -29,9 +29,8 @@ function ask() {
    }

    exports.iTunesTrackId = result.trackId;
    _ask();

    return;
    return ask();
    });

    return;
    @@ -50,12 +49,12 @@ function ask() {
    alertDialog.addEventListener('click', function(e) {

    if (buttonNames[e.index] === exports.yes) {
    Ti.App.Properties.setBool('rate_done', true);
    Ti.App.Properties.setString('rate_done', Ti.App.version);

    show();
    open();

    } else if (buttonNames[e.index] === exports.never) {
    Ti.App.Properties.setBool('rate_done', true);
    Ti.App.Properties.setBool('rate_never', true);
    }

    return;
    @@ -98,16 +97,24 @@ function reset() {
    Ti.API.debug('[RATE] Reset.');

    Ti.App.Properties.removeProperty('rate_done');
    Ti.App.Properties.removeProperty('rate_never');
    Ti.App.Properties.removeProperty('rate_points');
    Ti.App.Properties.removeProperty('rate_asked');

    return;
    }

    function _trigger(_points, _show) {

    if (Ti.App.Properties.getBool('rate_never', false) === true) {
    Ti.API.debug('[RATE] Rating disabled by user.');
    return;
    }

    if (Ti.App.Properties.getBool('rate_done', false) === true) {
    Ti.API.debug('[RATE] Rating already done or rejected.');
    var rate_done = Ti.App.Properties.getString('rate_done');

    if (exports.eachVersion ? (rate_done === Ti.App.version) : rate_done) {
    Ti.API.debug('[RATE] Rating already done.');
    return;
    }

    @@ -121,7 +128,19 @@ function _trigger(_points, _show) {
    var now = (new Date() / 1000),
    checked = Ti.App.Properties.getInt('rate_asked', 0);

    if (_show !== false && points >= exports.pointsBetween && (now - checked) >= (exports.daysBetween * 86400)) {
    if (_show !== false) {

    if (points < exports.pointsBetween) {
    Ti.API.debug('[RATE] Not enough points: ' + points + ' of ' + exports.pointsBetween);
    _show = false;

    } else if (checked === 0 || (now - checked) < (exports.daysBetween * 86400)) {
    Ti.API.debug('[RATE] Not enough days: ' + Math.round((now - checked) / 86400) + ' of ' + exports.daysBetween);
    _show = false;
    }
    }

    if (_show !== false) {
    Ti.API.debug('[RATE] Rating triggered!');

    Ti.App.Properties.setInt('rate_points', 0);
    @@ -148,19 +167,19 @@ function _lookup(_callback) {
    return;

    } else {
    Ti.API.error('[XHR:response] ' + this.responseText);
    Ti.API.error('[RATE] LOOKUP ERROR ' + this.responseText);
    }

    } catch (err) {
    Ti.API.error('[XHR:json] ' + JSON.stringify(err));
    Ti.API.error('[RATE] LOOKUP ERROR ' + JSON.stringify(err));
    }
    }

    _callback();
    return;
    },
    onerror: function (e) {
    Ti.API.error('[XHR:error] ' + JSON.stringify(e.error));
    Ti.API.error('[RATE] LOOKUP ERROR ' + JSON.stringify(e.error));
    _callback();
    return;
    }
    @@ -173,7 +192,7 @@ function _lookup(_callback) {
    } else {
    url = url + 'bundleId=' + Ti.App.id;
    }

    xhr.open('GET', url);
    xhr.send();

    @@ -189,6 +208,7 @@ exports.never = 'No, thank you';
    exports.iTunesTrackId = null;
    exports.daysBetween = 3;
    exports.pointsBetween = 3;
    exports.eachVersion = false;

    exports.plus = plus;
    exports.test = test;
  9. FokkeZB revised this gist May 6, 2013. 2 changed files with 116 additions and 97 deletions.
    4 changes: 2 additions & 2 deletions advanced.js
    Original file line number Diff line number Diff line change
    @@ -8,8 +8,8 @@ rate.later = 'Maybe later';
    rate.never = 'Forget it';

    // Set triggers
    rate.minimumPoints = 100; // Reach 100 points before asking and between each repeat
    rate.maxRepeats = 10; // How many times shall we ask?
    rate.pointsBetween = 100; // Reach 100 points before asking and between each repeat
    rate.daysBetween = 10; // Wait 10 days before asking and between each repeat

    // Set iTunes Track ID manually
    rate.iTunesTrackId = 123456;
    209 changes: 114 additions & 95 deletions rate.js
    Original file line number Diff line number Diff line change
    @@ -13,99 +13,49 @@ function test() {
    return _trigger();
    }

    function show() {
    return _ask(true);
    }

    function reset() {
    Ti.API.debug('[RATE] Reset.');

    _property('done', 0);
    _property('repeats', 0);
    _property('points', 0);

    return;
    }

    function _trigger(_points, _show) {

    if (_property('done')) {
    Ti.API.debug('[RATE] Rating already done or rejected.');
    return;
    }

    if (_property('repeats') >= exports.maxRepeats) {
    Ti.API.debug('[RATE] Rating repeat reached maximum: ' + exports.maxRepeats);
    return;
    }

    if (_points) {
    _property('points', _property('points') + (_points || 1));
    Ti.API.debug('[RATE] Rating points changed to: ' + _property('points'));
    }

    if (_show === false) {
    return;
    }

    if (_property('points') >= exports.minimumPoints) {
    Ti.API.debug('[RATE] Rating triggered!');

    _property('repeats', _property('repeats') + 1);
    _property('points', 0);

    _ask();
    }

    return;
    }

    function _ask(forced) {
    function ask() {

    if (typeof _platform !== 'string') {
    _platform = Ti.Platform.name;
    }

    if (_platform === 'iPhone OS' && !exports.iTunesTrackId) {
    _lookup(forced);

    _lookup(function (result) {

    if (!result) {
    Ti.API.debug('[RATE] Lookup failed.');
    return;
    }

    exports.iTunesTrackId = result.trackId;
    _ask();

    return;
    });

    return;
    }

    var buttonNames;

    if (forced) {
    buttonNames = [exports.yes, exports.later];
    } else if (_property('repeats') >= exports.maxRepeats) {
    buttonNames = [exports.yes, exports.never];
    } else {
    buttonNames = [exports.yes, exports.later, exports.never];
    }

    if (_platform === 'iPhone OS' && buttonNames.length === 2) {
    buttonNames.reverse();
    }
    var buttonNames = [exports.yes, exports.later, exports.never];
    var cancel = buttonNames.length - 1;

    var alertDialog = Titanium.UI.createAlertDialog({
    title: exports.title,
    message: exports.message,
    buttonNames: buttonNames,
    cancel: buttonNames.length - 1
    cancel: cancel
    });

    alertDialog.addEventListener('click', function(e) {

    if (buttonNames[e.index] === exports.yes) {
    _property('done', 1);
    Ti.App.Properties.setBool('rate_done', true);

    if (Ti.Platform.name === 'android') {
    Ti.Platform.openURL('market://details?id=' + Ti.App.id);

    } else if (Ti.Platform.name === 'iPhone OS' && exports.iTunesTrackId) {
    Ti.Platform.openURL('itms-apps://itunes.apple.com/WebObjects/MZStore.woa/wa/viewContentsUserReviews?id=' + exports.iTunesTrackId + '&onlyLatestVersion=true&pageNumber=0&sortOrdering=1&type=Purple+Software');
    }
    show();

    } else if (buttonNames[e.index] === exports.never) {
    _property('done', 1);
    Ti.App.Properties.setBool('rate_done', true);
    }

    return;
    @@ -116,50 +66,118 @@ function _ask(forced) {
    return;
    }

    function _lookup(forced) {
    function open() {

    if (Ti.Platform.name === 'android') {
    Ti.Platform.openURL('market://details?id=' + Ti.App.id);

    } else if (Ti.Platform.name === 'iPhone OS') {

    if (!exports.iTunesTrackId) {
    _lookup(function (result) {

    if (!result) {
    Ti.API.debug('[RATE] Lookup failed.');
    return;
    }

    exports.iTunesTrackId = result.trackId;
    return open();
    });

    return;
    }

    Ti.Platform.openURL('itms-apps://itunes.apple.com/WebObjects/MZStore.woa/wa/viewContentsUserReviews?id=' + exports.iTunesTrackId + '&onlyLatestVersion=true&pageNumber=0&sortOrdering=1&type=Purple+Software');
    }

    return;
    }

    function reset() {
    Ti.API.debug('[RATE] Reset.');

    Ti.App.Properties.removeProperty('rate_done');
    Ti.App.Properties.removeProperty('rate_points');
    Ti.App.Properties.removeProperty('rate_asked');

    return;
    }

    function _trigger(_points, _show) {

    if (Ti.App.Properties.getBool('rate_done', false) === true) {
    Ti.API.debug('[RATE] Rating already done or rejected.');
    return;
    }

    var points = Ti.App.Properties.getInt('rate_points', 0);

    if (_points) {
    points = points + (_points || 1);
    Ti.API.debug('[RATE] Rating points changed to: ' + points);
    }

    var now = (new Date() / 1000),
    checked = Ti.App.Properties.getInt('rate_asked', 0);

    if (_show !== false && points >= exports.pointsBetween && (now - checked) >= (exports.daysBetween * 86400)) {
    Ti.API.debug('[RATE] Rating triggered!');

    Ti.App.Properties.setInt('rate_points', 0);
    Ti.App.Properties.setInt('rate_asked', now);

    ask();

    } else {
    Ti.App.Properties.setInt('rate_points', points);
    }

    return;
    }

    function _lookup(_callback) {
    var xhr = Ti.Network.createHTTPClient({
    onload: function (e) {
    if (xhr.status === 200 && this.responseText) {
    try {
    var json = JSON.parse(this.responseText);

    if (json.resultCount === 1 && json.results[0].trackId) {
    exports.iTunesTrackId = json.results[0].trackId;
    _ask(forced);
    if (json.resultCount === 1) {
    _callback(json.results[0]);
    return;

    } else {
    Ti.API.error('[RATE:lookup] ' + this.responseText);
    Ti.API.error('[XHR:response] ' + this.responseText);
    }

    } catch (err) {
    Ti.API.error('[RATE:xhr] ' + JSON.stringify(err));
    Ti.API.error('[XHR:json] ' + JSON.stringify(err));
    }
    }

    _callback();
    return;
    },
    onerror: function (e) {
    Ti.API.error('[RATE:xhr] ' + JSON.stringify(e.error));
    Ti.API.error('[XHR:error] ' + JSON.stringify(e.error));
    _callback();
    return;
    }
    });

    xhr.open('GET', 'http://itunes.apple.com/lookup?bundleId=' + Ti.App.id);
    xhr.send();

    return;
    }

    function _property(key, value) {
    var url = 'http://itunes.apple.com/lookup?';

    if (typeof value === 'number') {
    _properties[key] = value;
    Ti.App.Properties.setInt('rate_' + key, value);

    } else if (typeof _properties[key] !== 'number') {
    _properties[key] = Ti.App.Properties.getInt('rate_' + key, 0);
    if (exports.iTunesTrackId) {
    url = url + 'id=' + exports.iTunesTrackId;
    } else {
    url = url + 'bundleId=' + Ti.App.id;
    }

    return _properties[key];
    xhr.open('GET', url);
    xhr.send();

    return;
    }

    exports.title = 'Like our app?';
    @@ -169,10 +187,11 @@ exports.later = 'Ask me later';
    exports.never = 'No, thank you';

    exports.iTunesTrackId = null;
    exports.minimumPoints = 3;
    exports.maxRepeats = 3;
    exports.daysBetween = 3;
    exports.pointsBetween = 3;

    exports.plus = plus;
    exports.test = test;
    exports.show = show;
    exports.ask = ask;
    exports.open = open;
    exports.reset = reset;
  10. FokkeZB revised this gist Apr 26, 2013. 1 changed file with 29 additions and 38 deletions.
    67 changes: 29 additions & 38 deletions rate.js
    Original file line number Diff line number Diff line change
    @@ -1,13 +1,4 @@
    var title = 'Like our app?',
    message = 'Please take a minute to rate it:',
    yes = 'Yes, of course',
    later = 'Ask me later',
    never = 'No, thank you',
    iTunesTrackId,
    minimumPoints = 3,
    maxRepeats = 3,
    properties = {},
    _platform;
    var _properties = {}, _platform;

    function plus(_points, _show) {

    @@ -43,8 +34,8 @@ function _trigger(_points, _show) {
    return;
    }

    if (_property('repeats') >= maxRepeats) {
    Ti.API.debug('[RATE] Rating repeat reached maximum: ' + maxRepeats);
    if (_property('repeats') >= exports.maxRepeats) {
    Ti.API.debug('[RATE] Rating repeat reached maximum: ' + exports.maxRepeats);
    return;
    }

    @@ -57,7 +48,7 @@ function _trigger(_points, _show) {
    return;
    }

    if (_property('points') >= minimumPoints) {
    if (_property('points') >= exports.minimumPoints) {
    Ti.API.debug('[RATE] Rating triggered!');

    _property('repeats', _property('repeats') + 1);
    @@ -75,45 +66,45 @@ function _ask(forced) {
    _platform = Ti.Platform.name;
    }

    if (_platform === 'iPhone OS' && !iTunesTrackId) {
    if (_platform === 'iPhone OS' && !exports.iTunesTrackId) {
    _lookup(forced);
    return;
    }

    var buttonNames;

    if (forced) {
    buttonNames = [yes, later];
    } else if (_property('repeats') >= maxRepeats) {
    buttonNames = [yes, never];
    buttonNames = [exports.yes, exports.later];
    } else if (_property('repeats') >= exports.maxRepeats) {
    buttonNames = [exports.yes, exports.never];
    } else {
    buttonNames = [yes, later, never];
    buttonNames = [exports.yes, exports.later, exports.never];
    }

    if (_platform === 'iPhone OS' && buttonNames.length === 2) {
    buttonNames.reverse();
    }

    var alertDialog = Titanium.UI.createAlertDialog({
    title: title,
    message: message,
    title: exports.title,
    message: exports.message,
    buttonNames: buttonNames,
    cancel: buttonNames.length - 1
    });

    alertDialog.addEventListener('click', function(e) {

    if (buttonNames[e.index] === yes) {
    if (buttonNames[e.index] === exports.yes) {
    _property('done', 1);

    if (Ti.Platform.name === 'android') {
    Ti.Platform.openURL('market://details?id=' + Ti.App.id);

    } else if (Ti.Platform.name === 'iPhone OS' && iTunesTrackId) {
    Ti.Platform.openURL('itms-apps://itunes.apple.com/WebObjects/MZStore.woa/wa/viewContentsUserReviews?id=' + iTunesTrackId + '&onlyLatestVersion=true&pageNumber=0&sortOrdering=1&type=Purple+Software');
    } else if (Ti.Platform.name === 'iPhone OS' && exports.iTunesTrackId) {
    Ti.Platform.openURL('itms-apps://itunes.apple.com/WebObjects/MZStore.woa/wa/viewContentsUserReviews?id=' + exports.iTunesTrackId + '&onlyLatestVersion=true&pageNumber=0&sortOrdering=1&type=Purple+Software');
    }

    } else if (buttonNames[e.index] === never) {
    } else if (buttonNames[e.index] === exports.never) {
    _property('done', 1);
    }

    @@ -133,7 +124,7 @@ function _lookup(forced) {
    var json = JSON.parse(this.responseText);

    if (json.resultCount === 1 && json.results[0].trackId) {
    iTunesTrackId = json.results[0].trackId;
    exports.iTunesTrackId = json.results[0].trackId;
    _ask(forced);

    } else {
    @@ -161,25 +152,25 @@ function _lookup(forced) {
    function _property(key, value) {

    if (typeof value === 'number') {
    properties[key] = value;
    _properties[key] = value;
    Ti.App.Properties.setInt('rate_' + key, value);

    } else if (typeof properties[key] !== 'number') {
    properties[key] = Ti.App.Properties.getInt('rate_' + key, 0);
    } else if (typeof _properties[key] !== 'number') {
    _properties[key] = Ti.App.Properties.getInt('rate_' + key, 0);
    }

    return properties[key];
    return _properties[key];
    }

    exports.title = title;
    exports.message = message;
    exports.yes = yes;
    exports.later = later;
    exports.never = never;
    exports.title = 'Like our app?';
    exports.message = 'Please take a minute to rate it:';
    exports.yes = 'Yes, of course';
    exports.later = 'Ask me later';
    exports.never = 'No, thank you';

    exports.iTunesTrackId = iTunesTrackId;
    exports.minimumPoints = minimumPoints;
    exports.maxRepeats = maxRepeats;
    exports.iTunesTrackId = null;
    exports.minimumPoints = 3;
    exports.maxRepeats = 3;

    exports.plus = plus;
    exports.test = test;
  11. FokkeZB revised this gist Apr 26, 2013. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion advanced.js
    Original file line number Diff line number Diff line change
    @@ -11,7 +11,7 @@ rate.never = 'Forget it';
    rate.minimumPoints = 100; // Reach 100 points before asking and between each repeat
    rate.maxRepeats = 10; // How many times shall we ask?

    // Set iTunes Track ID
    // Set iTunes Track ID manually
    rate.iTunesTrackId = 123456;

    // Reset counts (WARNING: Will also reset the user's wish to never be asked again!)
  12. FokkeZB revised this gist Apr 26, 2013. 2 changed files with 1 addition and 1 deletion.
    1 change: 0 additions & 1 deletion gistfile1.txt
    Original file line number Diff line number Diff line change
    @@ -1 +0,0 @@
    df
    1 change: 1 addition & 0 deletions simple.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1 @@
    require('rate').plus();
  13. FokkeZB created this gist Apr 26, 2013.
    9 changes: 9 additions & 0 deletions RATING.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,9 @@
    I wanted a intelligent library that pops the "Rate my app" question at the right time and is easy to set-up.

    Well, this library at minimum requires no configuration at all and takes just a single line of code, because it reads your app's (bundle) ID from `Ti.App.id` and looks up the App Store ID itself:

    `require('rate').plus();`

    Check out `advanced.js` for all available options.

    I personally like to add points at places where the user has positive interaction with the app, but wait to pop the question until he/she is finished doing that.
    30 changes: 30 additions & 0 deletions advanced.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,30 @@
    var rate = require('rate');

    // Set texts
    rate.title = 'Pleeeeease rate!';
    rate.message = 'I would be so thankful!';
    rate.yes = 'Fine';
    rate.later = 'Maybe later';
    rate.never = 'Forget it';

    // Set triggers
    rate.minimumPoints = 100; // Reach 100 points before asking and between each repeat
    rate.maxRepeats = 10; // How many times shall we ask?

    // Set iTunes Track ID
    rate.iTunesTrackId = 123456;

    // Reset counts (WARNING: Will also reset the user's wish to never be asked again!)
    rate.reset();

    // Add 1 point and test if we should ask
    rate.plus();

    // Add more points and do not test
    rate.plus(5, false);

    // Just test
    rate.test();

    // Just ask
    rate.show();
    1 change: 1 addition & 0 deletions gistfile1.txt
    Original file line number Diff line number Diff line change
    @@ -0,0 +1 @@
    df
    187 changes: 187 additions & 0 deletions rate.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,187 @@
    var title = 'Like our app?',
    message = 'Please take a minute to rate it:',
    yes = 'Yes, of course',
    later = 'Ask me later',
    never = 'No, thank you',
    iTunesTrackId,
    minimumPoints = 3,
    maxRepeats = 3,
    properties = {},
    _platform;

    function plus(_points, _show) {

    if (typeof _points !== 'number') {
    _points = 1;
    }

    return _trigger(_points, _show);
    }

    function test() {
    return _trigger();
    }

    function show() {
    return _ask(true);
    }

    function reset() {
    Ti.API.debug('[RATE] Reset.');

    _property('done', 0);
    _property('repeats', 0);
    _property('points', 0);

    return;
    }

    function _trigger(_points, _show) {

    if (_property('done')) {
    Ti.API.debug('[RATE] Rating already done or rejected.');
    return;
    }

    if (_property('repeats') >= maxRepeats) {
    Ti.API.debug('[RATE] Rating repeat reached maximum: ' + maxRepeats);
    return;
    }

    if (_points) {
    _property('points', _property('points') + (_points || 1));
    Ti.API.debug('[RATE] Rating points changed to: ' + _property('points'));
    }

    if (_show === false) {
    return;
    }

    if (_property('points') >= minimumPoints) {
    Ti.API.debug('[RATE] Rating triggered!');

    _property('repeats', _property('repeats') + 1);
    _property('points', 0);

    _ask();
    }

    return;
    }

    function _ask(forced) {

    if (typeof _platform !== 'string') {
    _platform = Ti.Platform.name;
    }

    if (_platform === 'iPhone OS' && !iTunesTrackId) {
    _lookup(forced);
    return;
    }

    var buttonNames;

    if (forced) {
    buttonNames = [yes, later];
    } else if (_property('repeats') >= maxRepeats) {
    buttonNames = [yes, never];
    } else {
    buttonNames = [yes, later, never];
    }

    if (_platform === 'iPhone OS' && buttonNames.length === 2) {
    buttonNames.reverse();
    }

    var alertDialog = Titanium.UI.createAlertDialog({
    title: title,
    message: message,
    buttonNames: buttonNames,
    cancel: buttonNames.length - 1
    });

    alertDialog.addEventListener('click', function(e) {

    if (buttonNames[e.index] === yes) {
    _property('done', 1);

    if (Ti.Platform.name === 'android') {
    Ti.Platform.openURL('market://details?id=' + Ti.App.id);

    } else if (Ti.Platform.name === 'iPhone OS' && iTunesTrackId) {
    Ti.Platform.openURL('itms-apps://itunes.apple.com/WebObjects/MZStore.woa/wa/viewContentsUserReviews?id=' + iTunesTrackId + '&onlyLatestVersion=true&pageNumber=0&sortOrdering=1&type=Purple+Software');
    }

    } else if (buttonNames[e.index] === never) {
    _property('done', 1);
    }

    return;
    });

    alertDialog.show();

    return;
    }

    function _lookup(forced) {
    var xhr = Ti.Network.createHTTPClient({
    onload: function (e) {
    if (xhr.status === 200 && this.responseText) {
    try {
    var json = JSON.parse(this.responseText);

    if (json.resultCount === 1 && json.results[0].trackId) {
    iTunesTrackId = json.results[0].trackId;
    _ask(forced);

    } else {
    Ti.API.error('[RATE:lookup] ' + this.responseText);
    }

    } catch (err) {
    Ti.API.error('[RATE:xhr] ' + JSON.stringify(err));
    }
    }
    return;
    },
    onerror: function (e) {
    Ti.API.error('[RATE:xhr] ' + JSON.stringify(e.error));
    return;
    }
    });

    xhr.open('GET', 'http://itunes.apple.com/lookup?bundleId=' + Ti.App.id);
    xhr.send();

    return;
    }

    function _property(key, value) {

    if (typeof value === 'number') {
    properties[key] = value;
    Ti.App.Properties.setInt('rate_' + key, value);

    } else if (typeof properties[key] !== 'number') {
    properties[key] = Ti.App.Properties.getInt('rate_' + key, 0);
    }

    return properties[key];
    }

    exports.title = title;
    exports.message = message;
    exports.yes = yes;
    exports.later = later;
    exports.never = never;

    exports.iTunesTrackId = iTunesTrackId;
    exports.minimumPoints = minimumPoints;
    exports.maxRepeats = maxRepeats;

    exports.plus = plus;
    exports.test = test;
    exports.show = show;
    exports.reset = reset;