diff --git a/Makefile b/Makefile index 8e6313b7..2ecf2df2 100644 --- a/Makefile +++ b/Makefile @@ -10,9 +10,9 @@ EXTERN=Web-SDK/src/extern.js .PHONY: clean -all: dist/build.min.js dist/build.js Reference.md README.md +all: dist/build.min.js dist/build.js Reference.md clean: - rm -f dist/** docs/cordova/3_branch_cordova.md Reference.md README.md + rm -f dist/** docs/cordova/3_branch_cordova.md Reference.md # Kinda gross, but will download closure compiler if you don't have it. compiler/compiler.jar: diff --git a/Reference.md b/Reference.md index 23677890..eb686daa 100644 --- a/Reference.md +++ b/Reference.md @@ -1,5 +1,3 @@ -# Branch Cordova Reference - 1. Branch Session + [.init()](#initbranch_key-options-callback) + [.data()](#datacallback) @@ -14,6 +12,8 @@ 3. Deep Linking + [.link()](#linkdata-callback) + [.sendSMS()](#sendsmsphone-linkdata-options-callback) + + [.deepview()](#deepviewdata-options-callback) + + [.deepviewCta()](#deepviewcta) 4. Referrals and Credits + [.referrals()](#referralscallback) @@ -26,6 +26,11 @@ ___ + + + + + * * * ### setDebug(debug) @@ -51,7 +56,8 @@ ___ **options**: `Object`, _optional_ - { *isReferrable*: _Is this a referrable session_ }. -**callback**: `function`, _optional_ - callback to read the session data. +**callback**: `function`, _optional_ - callback to read the +session data. THE "isReferrable" OPTION IS ONLY USED IN THE CORDOVA/PHONEGAP PLUGIN AND THE TITANIUM MODULE @@ -61,7 +67,8 @@ object with all the external methods described below. All calls made to Branch methods are stored in a queue, so even if the SDK is not fully instantiated, calls made to it will be queued in the order they were originally called. -If the session was opened from a referring link, `data()` will also return the referring link click as `referring_link`, which gives you the ability to continue the click flow. +If the session was opened from a referring link, `data()` will also return the referring link +click as `referring_link`, which gives you the ability to continue the click flow. The init function on the Branch object initiates the Branch session and creates a new user session, if it doesn't already exist, in @@ -88,7 +95,7 @@ callback( referring_identity: '12345', // If the user was referred from a link, and the link was created by a user with an identity, that identity is here. has_app: true, // Does the user have the app installed already? identity: 'BranchUser', // Unique string that identifies the user - referring_link: 'https://bnc.lt/c/jgg75-Gjd3' // The referring link click, if available. + referring_link: 'https://bnc.lt/c/jgg75-Gjd3' // The referring link click, if available. } ); ``` @@ -102,7 +109,8 @@ ___ **Parameters** -**callback**: `function`, _optional_ - callback to read the session data. +**callback**: `function`, _optional_ - callback to read the +session data. Returns the same session information and any referring data, as `Branch.init`, but does not require the `app_id`. This is meant to be called @@ -118,7 +126,8 @@ ___ **Parameters** -**callback**: `function`, _optional_ - callback to read the session data. +**callback**: `function`, _optional_ - callback to read the +session data. Returns the same session information and any referring data, as `Branch.init` did when the app was first installed. This is meant to be called @@ -135,9 +144,11 @@ ___ **Parameters** -**identity**: `string`, _required_ - a string uniquely identifying the user - often a user ID or email address. +**identity**: `string`, _required_ - a string uniquely identifying the user - often a user ID +or email address. -**callback**: `function`, _optional_ - callback that returns the user's Branch identity id and unique link. +**callback**: `function`, _optional_ - callback that returns the user's +Branch identity id and unique link. **[Formerly `identify()`](CHANGELOG.md)** @@ -231,8 +242,9 @@ ___ **callback**: `function`, _optional_ -This function allows you to track any event with supporting metadata. Use the events you track to create funnels in the Branch dashboard. -The `metadata` parameter is a formatted JSON object that can contain any data and has limitless hierarchy. +This function allows you to track any event with supporting metadata. Use the events you track to +create funnels in the Branch dashboard. The `metadata` parameter is a formatted JSON object that +can contain any data and has limitless hierarchy. ##### Usage ```js @@ -261,7 +273,8 @@ ___ **data**: `Object`, _required_ - link data and metadata. -**callback**: `function`, _required_ - returns a string of the Branch deep linking URL. +**callback**: `function`, _required_ - returns a string of the Branch deep +linking URL. **[Formerly `createLink()`](CHANGELOG.md)** @@ -269,10 +282,13 @@ Creates and returns a deep linking URL. The `data` parameter can include an object with optional data you would like to store, including Facebook [Open Graph data](https://developers.facebook.com/docs/opengraph). -**data** The dictionary to embed with the link. Accessed as session or install parameters from the SDK. +**data** The dictionary to embed with the link. Accessed as session or install parameters from +the SDK. **Note** -You can customize the Facebook OG tags of each URL if you want to dynamically share content by using the following optional keys in the data dictionary. Please use this [Facebook tool](https://developers.facebook.com/tools/debug/og/object) to debug your OG tags! +You can customize the Facebook OG tags of each URL if you want to dynamically share content by +using the following optional keys in the data dictionary. Please use this +[Facebook tool](https://developers.facebook.com/tools/debug/og/object) to debug your OG tags! | Key | Value | --- | --- @@ -345,90 +361,121 @@ callback( -### sendSMS(phone, linkData, options, callback) +### deepview(data, options, callback) **Parameters** -**phone**: `string`, _required_ - phone number to send SMS to +**data**: `Object`, _required_ - object of all link data, same as branch.link(). -**linkData**: `Object`, _required_ - object of link data +**options**: `Object`, _optional_ - { *make_new_link*: _whether to create a new link even if +one already exists_. *open_app*, _whether to try to open the app passively (as opposed to +opening it upon user clicking); defaults to true_ +}. -**options**: `Object`, _optional_ - options: make_new_link, which forces the creation of a new link even if one already exists +**callback**: `function`, _optional_ - returns an error if the API call is unsuccessful -**callback**: `function`, _optional_ - Returns an error if unsuccessful +Turns the current page into a "deepview" – a preview of app content. This gives the page two +special behaviors: (1) when the page is viewed on a mobile browser, if the user has the app +installed on their phone, we will try to open the app automaticaly and deeplink them to this +content (this can be toggled off by turning open_app to false, but this is not recommended), +and (2) provides a callback to open the app directly, accessible as `branch.deepviewCta()`; +you'll want to have a button on your web page that says something like "View in app", which +calls this function. -**[Formerly `SMSLink()`](CHANGELOG.md)** - -A robust function to give your users the ability to share links via SMS. If -the user navigated to this page via a Branch link, `sendSMS` will send that -same link. Otherwise, it will create a new link with the data provided in -the `params` argument. `sendSMS` also registers a click event with the -`channel` pre-filled with `'sms'` before sending an sms to the provided -`phone` parameter. This way the entire link click event is recorded starting -with the user sending an sms. - -**Note**: `sendSMS` will *automatically* send a previously generated link click, -along with the `data` object in the original link. Therefore, it is unneccessary for the -`data()` method to be called to check for an already existing link. If a link already -exists, `sendSMS` will simply ignore the `data` object passed to it, and send the existing link. -If this behaivior is not desired, set `make_new_link: true` in the `options` object argument -of `sendSMS`, and `sendSMS` will always make a new link. - -**Supports international SMS**. +See [this tutorial](https://blog.branch.io/how-to-deep-link-from-your-mobile-website) for a full +guide on how to use the deepview functionality of the Web SDK. #### Usage ```js -branch.sendSMS( - phone, - linkData, +branch.deepview( + data, options, - callback (err, data) + callback (err) ); ``` -##### Example +#### Example ```js -branch.sendSMS( - '9999999999', +branch.deepview( { - tags: ['tag1', 'tag2'], channel: 'facebook', - feature: 'dashboard', - stage: 'new user', data: { - mydata: 'something', + mydata: 'content of my data', foo: 'bar', - '$desktop_url': 'http://myappwebsite.com', - '$ios_url': 'http://myappwebsite.com/ios', - '$ipad_url': 'http://myappwebsite.com/ipad', - '$android_url': 'http://myappwebsite.com/android', - '$og_app_id': '12345', - '$og_title': 'My App', - '$og_description': 'My app\'s description.', - '$og_image_url': 'http://myappwebsite.com/image.png' - } + '$deepview_path': 'item_id=12345' + }, + feature: 'dashboard', + stage: 'new user', + tags: [ 'tag1', 'tag2' ], + }, + { + make_new_link: true, + open_app: true }, - { make_new_link: true }, // Default: false. If set to true, sendSMS will generate a new link even if one already exists. - function(err) { console.log(err); } + function(err) { + console.log(err || 'no error'); + } ); ``` ##### Callback Format ```js -callback("Error message"); +callback( + "Error message" +); +``` + + + +### deepviewCta() + +Perform the branch deepview CTA (call to action) on mobile after `branch.deepview()` call is +finished. If the `branch.deepview()` call is finished with no error, when `branch.deepviewCta()` is called, +an attempt is made to open the app and deeplink the end user into it; if the end user does not +have the app installed, they will be redirected to the platform-appropriate app stores. If on the +other hand, `branch.deepview()` returns with an error, `branch.deepviewCta()` will fall back to +redirect the user using +[Branch dynamic links](https://github.com/BranchMetrics/Deferred-Deep-Linking-Public-API#structuring-a-dynamic-deeplink). + +If `branch.deepview()` has not been called, an error will arise with a reminder to call +`branch.deepview()` first. + +##### Usage +```js +$('a.deepview-cta').click(branch.deepviewCta); // If you are using jQuery + +document.getElementById('my-elem').onClick = branch.deepviewCta; // Or generally + + // In HTML + +// We recommend to assign deepviewCta in deepview callback: +branch.deepview(data, option, function(err) { + if (err) { + throw err; + } + ${'a.deepview-cta').click(branch.deepviewCta); +}); + +// You can call this function any time after branch.deepview() is finished by simply: +branch.deepviewCta(); ``` ___ # Referral system rewarding functionality -In a standard referral system, you have 2 parties: the original user and the invitee. Our system is flexible enough to handle rewards for all users for any actions. Here are a couple example scenarios: +In a standard referral system, you have 2 parties: the original user and the invitee. Our system +is flexible enough to handle rewards for all users for any actions. Here are a couple example +scenarios: 1. Reward the original user for taking action (eg. inviting, purchasing, etc) 2. Reward the invitee for installing the app from the original user's referral link -3. Reward the original user when the invitee takes action (eg. give the original user credit when their the invitee buys something) +3. Reward the original user when the invitee takes action (eg. give the original user credit when + their the invitee buys something) -These reward definitions are created on the dashboard, under the 'Reward Rules' section in the 'Referrals' tab on the dashboard. +These reward definitions are created on the dashboard, under the 'Reward Rules' section in the +'Referrals' tab on the dashboard. -Warning: For a referral program, you should not use unique awards for custom events and redeem pre-identify call. This can allow users to cheat the system. +Warning: For a referral program, you should not use unique awards for custom events and redeem +pre-identify call. This can allow users to cheat the system. ## Retrieve referrals list @@ -484,14 +531,15 @@ callback( **callback**: `function`, _optional_ - returns an error if unsuccessful -Create a referral code using the supplied parameters. The code can be given to other users to enter. Applying the code will add credits to the referrer, referree or both. +Create a referral code using the supplied parameters. The code can be given to other users to +enter. Applying the code will add credits to the referrer, referree or both. The `options` object can containt the following properties: | Key | Value | --- | --- | amount | *reqruied* - An integer specifying the number of credits added when the code is applied. | calculation_type | *required* - An integer of 1 for unlimited uses, or 0 for one use. -| location | *required* - An integer that determines who get's the credits: 0 for the referree, 2 for the referring user or 3 for both. +| location | *required* - An integer that determines who gets the credits: 0 for the referree, 2 for the referring user or 3 for both. | bucket | *optional* - The bucket to apply the credits to. Defaults to "default". | prefix | *optional* - A string to be prepended to the code. | expiration | *optional* - A date string that if present, determines the date on which the code expires. @@ -660,7 +708,8 @@ callback( **options**: `Object`, _optional_ - options controlling the returned history. -**callback**: `function`, _required_ - returns an array with credit history data. +**callback**: `function`, _required_ - returns an array with credit history +data. This call will retrieve the entire history of credits and redemptions from the individual user. Properties available in the `options` object: @@ -744,7 +793,9 @@ ___ **[Formerly `redeemCredits()`](CHANGELOG.md)** -Credits are stored in `buckets`, which you can define as points, currency, whatever makes sense for your app. When you want to redeem credits, call this method with the number of points to be redeemed, and the bucket to redeem them from. +Credits are stored in `buckets`, which you can define as points, currency, whatever makes sense +for your app. When you want to redeem credits, call this method with the number of points to be +redeemed, and the bucket to redeem them from. ```js branch.redeem( diff --git a/Web-SDK b/Web-SDK index 00d24c60..740a3994 160000 --- a/Web-SDK +++ b/Web-SDK @@ -1 +1 @@ -Subproject commit 00d24c604d44e5508a631e0ee6dcc2b150880853 +Subproject commit 740a39944ab3314ee3e534995fdb541027a787c8 diff --git a/dist/build.js b/dist/build.js index 8c62e2ef..2f87d057 100644 --- a/dist/build.js +++ b/dist/build.js @@ -615,7 +615,7 @@ goog.tagUnsealableClass = function(a) { }; goog.UNSEALABLE_CONSTRUCTOR_PROPERTY_ = "goog_defineClass_legacy_unsealable"; // Input 1 -var config = {link_service_endpoint:"https://bnc.lt", api_endpoint:"https://api.branch.io", version:"1.7.1"}, WEB_BUILD = !1, CORDOVA_BUILD = !0, TITANIUM_BUILD = !1, IS_CORDOVA_APP = !!window.cordova; +var config = {link_service_endpoint:"https://bnc.lt", api_endpoint:"https://api.branch.io", version:"1.8.0"}, WEB_BUILD = !1, CORDOVA_BUILD = !0, TITANIUM_BUILD = !1, IS_CORDOVA_APP = !!window.cordova; IS_CORDOVA_APP && WEB_BUILD && window.alert("Please use Branch Cordova SDK instead. Visit https://github.com/BranchMetrics/Cordova-Ionic-PhoneGap-Deferred-Deep-Linking-SDK for more details."); // Input 2 var task_queue = function() { @@ -887,6 +887,7 @@ resources.credits = {destination:config.api_endpoint, endpoint:"/v1/credits", me resources.redeem = {destination:config.api_endpoint, endpoint:"/v1/redeem", method:utils.httpMethod.POST, params:defaults({amount:validator(!0, validationTypes.NUMBER), bucket:validator(!0, validationTypes.STRING), identity_id:validator(!0, branch_id)})}; resources.link = {destination:config.api_endpoint, endpoint:"/v1/url", method:utils.httpMethod.POST, ref:"obj", params:defaults({alias:validator(!1, validationTypes.STRING), campaign:validator(!1, validationTypes.STRING), channel:validator(!1, validationTypes.STRING), data:validator(!1, validationTypes.STRING), feature:validator(!1, validationTypes.STRING), identity_id:validator(!0, branch_id), stage:validator(!1, validationTypes.STRING), tags:validator(!1, validationTypes.ARRAY), type:validator(!1, validationTypes.NUMBER)})}; +resources.deepview = {destination:config.api_endpoint, endpoint:"/v1/deepview", jsonp:!0, method:utils.httpMethod.POST, params:defaults({campaign:validator(!1, validationTypes.STRING), channel:validator(!1, validationTypes.STRING), data:validator(!0, validationTypes.STRING), feature:validator(!1, validationTypes.STRING), link_click_id:validator(!1, validationTypes.STRING), open_app:validator(!1, validationTypes.BOOLEAN), stage:validator(!1, validationTypes.STRING), tags:validator(!1, validationTypes.ARRAY)})}; resources.hasApp = {destination:config.api_endpoint, endpoint:"/v1/has-app", method:utils.httpMethod.GET, params:{browser_fingerprint_id:validator(!0, branch_id)}}; resources.event = {destination:config.api_endpoint, endpoint:"/v1/event", method:utils.httpMethod.POST, params:defaults({event:validator(!0, validationTypes.STRING), metadata:validator(!0, validationTypes.OBJECT)})}; // Input 6 @@ -1330,9 +1331,12 @@ var sendSMS = function(a, b, c, d) { var f = b.iframe ? e.contentWindow.document : document; if (utils.mobileUserAgent()) { var g = a._referringLink(); - g && !b.make_new_link ? f.getElementById("branch-mobile-action").href = g : a.link(c, function(a, b) { - a || (f.getElementById("branch-mobile-action").href = b); - }); + g && !b.make_new_link ? f.getElementById("branch-mobile-action").href = g : (b.open_app = b.open_app, b.make_new_link = b.make_new_link, a.deepview(c, b, function(a) { + if (a) { + throw a; + } + f.getElementById("branch-mobile-action").onclick = "branch.deepviewCta()"; + })); } else { f.getElementById("sms-form").addEventListener("submit", function(d) { d.preventDefault(); @@ -1378,11 +1382,14 @@ var default_branch, callback_params = {NO_CALLBACK:0, CALLBACK_ERR:1, CALLBACK_E }, e = Array.prototype.slice.call(arguments)) : (e = Array.prototype.slice.call(arguments, 0, arguments.length - 1) || [], f = g); d._queue(function(g) { var h = function(b, c) { - if (b && a === callback_params.NO_CALLBACK) { - throw b; + try { + if (b && a === callback_params.NO_CALLBACK) { + throw b; + } + a === callback_params.CALLBACK_ERR ? f(b) : a === callback_params.CALLBACK_ERR_DATA && f(b, c); + } finally { + g(); } - a === callback_params.CALLBACK_ERR ? f(b) : a === callback_params.CALLBACK_ERR_DATA && f(b, c); - g(); }; if (!c) { if (d.init_state === init_states.INIT_PENDING) { @@ -1560,7 +1567,7 @@ Branch.prototype.logout = wrap(callback_params.CALLBACK_ERR, function(a) { b.identity_id = d.identity_id; b.identity = d.identity; session.update(b._storage, d); - a(c); + a(null); }); }); if (CORDOVA_BUILD || TITANIUM_BUILD) { @@ -1589,7 +1596,9 @@ Branch.prototype.link = wrap(callback_params.CALLBACK_ERR_DATA, function(a, b) { }); Branch.prototype.sendSMS = wrap(callback_params.CALLBACK_ERR, function(a, b, c, d) { function e(c) { - f._api(resources.SMSLinkSend, {link_url:c, phone:b}, a); + f._api(resources.SMSLinkSend, {link_url:c, phone:b}, function(b) { + a(b || null); + }); } var f = this; if ("function" === typeof d) { @@ -1615,6 +1624,39 @@ Branch.prototype.sendSMS = wrap(callback_params.CALLBACK_ERR, function(a, b, c, }); }); }); +Branch.prototype.deepview = wrap(callback_params.CALLBACK_ERR, function(a, b, c) { + var d = this; + c || (c = {}); + var e = config.link_service_endpoint + "/a/" + d.branch_key, f = !0, g; + for (g in b) { + b.hasOwnProperty(g) && "data" !== g && (f ? (e += "?", f = !1) : e += "&", e += encodeURIComponent(g) + "=" + encodeURIComponent(b[g])); + } + b = utils.cleanLinkData(b); + if (c.open_app || null === c.open_app || "undefined" === typeof c.open_app) { + b.open_app = !0; + } + (f = d._referringLink()) && !c.make_new_link && (b.link_click_id = f.substring(f.lastIndexOf("/") + 1, f.length)); + this._api(resources.deepview, b, function(b, c) { + if (b) { + return d._deepviewCta = function() { + d._windowRedirect(e); + }, a(b); + } + "function" === typeof c && (d._deepviewCta = c); + a(null); + }); +}); +Branch.prototype._windowRedirect = function(a) { + window.location = a; +}; +Branch.prototype.deepviewCta = wrap(callback_params.NO_CALLBACK, function(a) { + if ("undefined" === typeof this._deepviewCta) { + throw Error("Cannot call Deepview CTA, please call branch.deepview() first."); + } + window.event && (window.event.preventDefault ? window.event.preventDefault() : window.event.returnValue = !1); + this._deepviewCta(); + a(); +}); Branch.prototype.referrals = wrap(callback_params.CALLBACK_ERR_DATA, function(a) { this._api(resources.referrals, {}, a); }); @@ -1636,7 +1678,9 @@ Branch.prototype.creditHistory = wrap(callback_params.CALLBACK_ERR_DATA, functio this._api(resources.creditHistory, b || {}, a); }); Branch.prototype.redeem = wrap(callback_params.CALLBACK_ERR, function(a, b, c) { - this._api(resources.redeem, {amount:b, bucket:c}, a); + this._api(resources.redeem, {amount:b, bucket:c}, function(b) { + a(b || null); + }); }); WEB_BUILD && (Branch.prototype.addListener = function(a, b) { "function" === typeof a && void 0 === b && (b = a); @@ -1650,7 +1694,7 @@ WEB_BUILD && (Branch.prototype.addListener = function(a, b) { }, Branch.prototype.banner = wrap(callback_params.NO_CALLBACK, function(a, b, c) { "undefined" === typeof b.showAgain && "undefined" !== typeof b.forgetHide && (b.showAgain = b.forgetHide); var d = {icon:b.icon || "", title:b.title || "", description:b.description || "", openAppButtonText:b.openAppButtonText || "View in app", downloadAppButtonText:b.downloadAppButtonText || "Download App", sendLinkText:b.sendLinkText || "Send Link", phonePreviewText:b.phonePreviewText || "(999) 999-9999", iframe:"undefined" === typeof b.iframe ? !0 : b.iframe, showiOS:"undefined" === typeof b.showiOS ? !0 : b.showiOS, showiPad:"undefined" === typeof b.showiPad ? !0 : b.showiPad, showAndroid:"undefined" === - typeof b.showAndroid ? !0 : b.showAndroid, showDesktop:"undefined" === typeof b.showDesktop ? !0 : b.showDesktop, disableHide:!!b.disableHide, forgetHide:"number" === typeof b.forgetHide ? b.forgetHide : !!b.forgetHide, position:b.position || "top", customCSS:b.customCSS || "", mobileSticky:"undefined" === typeof b.mobileSticky ? !1 : b.mobileSticky, desktopSticky:"undefined" === typeof b.desktopSticky ? !0 : b.desktopSticky, make_new_link:!!b.make_new_link}; + typeof b.showAndroid ? !0 : b.showAndroid, showDesktop:"undefined" === typeof b.showDesktop ? !0 : b.showDesktop, disableHide:!!b.disableHide, forgetHide:"number" === typeof b.forgetHide ? b.forgetHide : !!b.forgetHide, position:b.position || "top", customCSS:b.customCSS || "", mobileSticky:"undefined" === typeof b.mobileSticky ? !1 : b.mobileSticky, desktopSticky:"undefined" === typeof b.desktopSticky ? !0 : b.desktopSticky, make_new_link:!!b.make_new_link, open_app:!!b.open_app}; "undefined" !== typeof b.showMobile && (d.showiOS = b.showMobile, d.showAndroid = b.showMobile); this.closeBannerPointer = banner(this, d, c, this._storage); a(); diff --git a/dist/build.min.js b/dist/build.min.js index a3a8b84a..0a6b828e 100644 --- a/dist/build.min.js +++ b/dist/build.min.js @@ -1,41 +1,44 @@ (function() {function f(b){var a=typeof b;if("object"==a)if(b){if(b instanceof Array)return"array";if(b instanceof Object)return a;var c=Object.prototype.toString.call(b);if("[object Window]"==c)return"object";if("[object Array]"==c||"number"==typeof b.length&&"undefined"!=typeof b.splice&&"undefined"!=typeof b.propertyIsEnumerable&&!b.propertyIsEnumerable("splice"))return"array";if("[object Function]"==c||"undefined"!=typeof b.call&&"undefined"!=typeof b.propertyIsEnumerable&&!b.propertyIsEnumerable("call"))return"function"}else return"null"; -else if("function"==a&&"undefined"==typeof b.call)return"object";return a};function k(){function b(){if(a.length)a[0](function(){a.shift();b()})}var a=[];return function(c){a.push(c);1===a.length&&b()}};function l(b){b=String(b);if(/^\s*$/.test(b)?0:/^[\],:{}\s\u2028\u2029]*$/.test(b.replace(/\\["\\\/bfnrtu]/g,"@").replace(/"[^"\\\n\r\u2028\u2029\x00-\x08\x0a-\x1f]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,"]").replace(/(?:^|:|,)(?:[\s\u2028\u2029]*\[)+/g,"")))try{return eval("("+b+")")}catch(a){}throw Error("Invalid JSON string: "+b);}function n(b){var a=[];p(new r,b,a);return a.join("")}function r(){} -function p(b,a,c){if(null==a)c.push("null");else{if("object"==typeof a){if("array"==f(a)){var d=a;a=d.length;c.push("[");for(var e="",g=0;gg?d+=String.fromCharCode(g):(127g?d+=String.fromCharCode(g>>6|192):(d+=String.fromCharCode(g>>12|224),d+=String.fromCharCode(g>>6&63|128)),d+=String.fromCharCode(g&63|128));for(b=d;q>2,c=(c&3)<<4|d>>4,h=(d&15)<<2|e>>6,m=e&63,isNaN(d)?m=h=64:isNaN(e)&&(m=64),a=a+"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".charAt(g)+ -"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".charAt(c)+"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".charAt(h)+"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".charAt(m);return a}function ba(b){if(!b)return null;-1g?e+=String.fromCharCode(g):(127g?e+=String.fromCharCode(g>>6|192):(e+=String.fromCharCode(g>>12|224),e+=String.fromCharCode(g>>6&63|128)),e+=String.fromCharCode(g&63|128));for(b=e;q>2,c=(c&3)<<4|e>>4,h=(e&15)<<2|d>>6,p=d&63,isNaN(e)?p=h=64:isNaN(d)&&(p=64),a=a+"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".charAt(g)+ +"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".charAt(c)+"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".charAt(h)+"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".charAt(p);return a}function ba(b){if(!b)return null;-1a.indexOf("?")?"?":"")+(c?b+c:"")+(0<=a.indexOf("/c/")?"&click=1":"")+"&callback="+g)} -function ra(b,a,c,d,e,g){var h=window.XMLHttpRequest?new XMLHttpRequest:new ActiveXObject("Microsoft.XMLHTTP");h.ontimeout=function(){g(Error("Request timed out"),null,504)};h.onerror=function(a){g(Error(a.error||"Error in API: "+h.status),null,h.status)};h.onreadystatechange=function(){if(4===h.readyState)if(200===h.status)try{g(null,l(h.responseText),h.status)}catch(a){g(null,{},h.status)}else 402===h.status?g(Error("Not enough credits to redeem."),null,h.status):"4"!==h.status.toString().substring(0, -1)&&"5"!==h.status.toString().substring(0,1)||g(Error("Error in API: "+h.status),null,h.status)};try{h.open(d,a,!0),h.timeout=5E3,h.setRequestHeader("Content-Type","application/x-www-form-urlencoded"),h.send(c)}catch(m){e.set("use_jsonp",!0),Q(b,a,c,d,g)}} -function sa(b,a,c,d,e){var g=pa(b,a,c);if(g.error)e(Error(g.error));else{var h,m="";"GET"===a.method?h=g.url+"?"+g.data:(h=g.url,m=g.data);var q=2,v=function(a,b,c){a&&0a.indexOf("?")?"?":"")+(c?b+c:"")+(0<=a.indexOf("/c/")?"&click=1":"")+"&callback="+g)} +function sa(b,a,c,e,d,g){var h=window.XMLHttpRequest?new XMLHttpRequest:new ActiveXObject("Microsoft.XMLHTTP");h.ontimeout=function(){g(Error("Request timed out"),null,504)};h.onerror=function(a){g(Error(a.error||"Error in API: "+h.status),null,h.status)};h.onreadystatechange=function(){if(4===h.readyState)if(200===h.status)try{g(null,l(h.responseText),h.status)}catch(a){g(null,{},h.status)}else 402===h.status?g(Error("Not enough credits to redeem."),null,h.status):"4"!==h.status.toString().substring(0, +1)&&"5"!==h.status.toString().substring(0,1)||g(Error("Error in API: "+h.status),null,h.status)};try{h.open(e,a,!0),h.timeout=5E3,h.setRequestHeader("Content-Type","application/x-www-form-urlencoded"),h.send(c)}catch(p){d.set("use_jsonp",!0),Q(b,a,c,e,g)}} +function ta(b,a,c,e,d){var g=qa(b,a,c);if(g.error)d(Error(g.error));else{var h,p="";"GET"===a.method?h=g.url+"?"+g.data:(h=g.url,p=g.data);var q=2,v=function(a,b,c){a&&0 // In HTML + +// We recommend to assign deepviewCta in deepview callback: +branch.deepview(data, option, function(err) { + if (err) { + throw err; + } + ${'a.deepview-cta').click(branch.deepviewCta); +}); + +// You can call this function any time after branch.deepview() is finished by simply: +branch.deepviewCta(); ``` ___ # Referral system rewarding functionality -In a standard referral system, you have 2 parties: the original user and the invitee. Our system is flexible enough to handle rewards for all users for any actions. Here are a couple example scenarios: +In a standard referral system, you have 2 parties: the original user and the invitee. Our system +is flexible enough to handle rewards for all users for any actions. Here are a couple example +scenarios: 1. Reward the original user for taking action (eg. inviting, purchasing, etc) 2. Reward the invitee for installing the app from the original user's referral link -3. Reward the original user when the invitee takes action (eg. give the original user credit when their the invitee buys something) +3. Reward the original user when the invitee takes action (eg. give the original user credit when + their the invitee buys something) -These reward definitions are created on the dashboard, under the 'Reward Rules' section in the 'Referrals' tab on the dashboard. +These reward definitions are created on the dashboard, under the 'Reward Rules' section in the +'Referrals' tab on the dashboard. -Warning: For a referral program, you should not use unique awards for custom events and redeem pre-identify call. This can allow users to cheat the system. +Warning: For a referral program, you should not use unique awards for custom events and redeem +pre-identify call. This can allow users to cheat the system. ## Retrieve referrals list @@ -462,7 +504,8 @@ callback( **callback**: `function`, _optional_ - returns an error if unsuccessful -Create a referral code using the supplied parameters. The code can be given to other users to enter. Applying the code will add credits to the referrer, referree or both. +Create a referral code using the supplied parameters. The code can be given to other users to +enter. Applying the code will add credits to the referrer, referree or both. The `options` object can containt the following properties: | Key | Value @@ -638,7 +681,8 @@ callback( **options**: `Object`, _optional_ - options controlling the returned history. -**callback**: `function`, _required_ - returns an array with credit history data. +**callback**: `function`, _required_ - returns an array with credit history +data. This call will retrieve the entire history of credits and redemptions from the individual user. Properties available in the `options` object: @@ -722,7 +766,9 @@ ___ **[Formerly `redeemCredits()`](CHANGELOG.md)** -Credits are stored in `buckets`, which you can define as points, currency, whatever makes sense for your app. When you want to redeem credits, call this method with the number of points to be redeemed, and the bucket to redeem them from. +Credits are stored in `buckets`, which you can define as points, currency, whatever makes sense +for your app. When you want to redeem credits, call this method with the number of points to be +redeemed, and the bucket to redeem them from. ```js branch.redeem(