Skip to content

Commit 250e07e

Browse files
Rc api final (#287)
* first draft * removed a check * un reachable remote conf * final form * latest version * warning changed to legacy api usage * Update CHANGELOG.md * update * pushed * new cond * erased * expilicite * comments * B * example Co-authored-by: ArtursKadikis <[email protected]>
1 parent 030fdca commit 250e07e

File tree

3 files changed

+60
-22
lines changed

3 files changed

+60
-22
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22
- ! Minor breaking change ! If no domain whitelist is provided for the heatmaps the SDK will fallback to your server url
33
- Fixed a bug where heatmap files were susceptible to DOM XSS
44
- Users can now input their domain whitelist for heatmaps feature during init
5+
- Implementing new Remote Config/AB testing API:
6+
- Added an init time flag to enable/disable new remote config API (default: disabled)
7+
- Added a new call to opt in users to the A/B testing for the given keys
8+
- Added an init time flag to enable/disable automatically opting in users for A/B testing while fetching remote config (with new RC API)(default: enabled)
59

610
## 22.06.1
711
- Added SDK calls to report Feedback widgets manually

examples/example_remote_config.html

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
app_key: "YOUR_APP_KEY",
1414
url: "https://try.count.ly", //your server goes here
1515
debug: true,
16+
rc_automatic_optin_for_ab: true, // set it to false for not opting in users for AB testing while fetching the remote config (only with latest API)
17+
use_explicit_rc_api: false, // set it to true to use the latest API
1618
remote_config: function (err, configs) {
1719
//handle initial remote configs here
1820
console.log(err, configs);
@@ -31,19 +33,25 @@ <h1>Remote Config</h1>
3133
<center>
3234
<img src="./images/team_countly.jpg" id="wallpaper" />
3335
<br />
34-
<input type="button" onclick="reloadConfig()" value="Reload Config">
36+
<input type="button" onclick="fetchConfig()" value="Fetch Config">
3537
<input type="button" onclick="getConfig()" value="Get Config">
3638
<input type="button" onclick="getConfig('test')" value="Get config for key Test">
39+
<input type="button" onclick="ab(['key1','key2'])" value="Enroll user to AB test">
3740
<p><a href='http://count.ly/'>Count.ly</a></p>
3841
</center>
3942
<script type='text/javascript'>
40-
//reload configs
41-
function reloadConfig(ob) {
43+
// fetches all keys
44+
function fetchConfig() {
4245
Countly.fetch_remote_config(function (err, config) {
4346
alert(JSON.stringify(config));
4447
});
4548
}
4649

50+
// enroll user
51+
function ab(keyArray) {
52+
Countly.enrollUserToAb(keyArray);
53+
}
54+
4755
//get config
4856
function getConfig(key) {
4957
alert(JSON.stringify(Countly.get_remote_config(key)));

lib/countly.js

Lines changed: 45 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,8 @@
255255
this.onload = getConfig("onload", ob, []);
256256
this.utm = getConfig("utm", ob, { source: true, medium: true, campaign: true, term: true, content: true });
257257
this.ignore_prefetch = getConfig("ignore_prefetch", ob, true);
258+
this.rcAutoOptinAb = getConfig("rc_automatic_optin_for_ab", ob, true);
259+
this.useExplicitRcApi = getConfig("use_explicit_rc_api", ob, false);
258260
this.debug = getConfig("debug", ob, false);
259261
this.test_mode = getConfig("test_mode", ob, false);
260262
this.metrics = getConfig("metrics", ob, {});
@@ -292,6 +294,11 @@
292294
lsSupport = false;
293295
}
294296

297+
if (!this.rcAutoOptinAb && !this.useExplicitRcApi) {
298+
log(logLevelEnums.WARNING, "initialize, Auto opting is disabled, switching to explicit RC API");
299+
this.useExplicitRcApi = true;
300+
}
301+
295302
if (!Array.isArray(ignoreReferrers)) {
296303
ignoreReferrers = [];
297304
}
@@ -426,6 +433,12 @@
426433
if (this.remote_config) {
427434
log(logLevelEnums.DEBUG, "initialize, remote_config callback provided:[" + !!this.remote_config + "]");
428435
}
436+
if (typeof this.rcAutoOptinAb === "boolean") {
437+
log(logLevelEnums.DEBUG, "initialize, automatic RC optin is enabled:[" + this.rcAutoOptinAb + "]");
438+
}
439+
if (!this.useExplicitRcApi) {
440+
log(logLevelEnums.WARNING, "initialize, will use legacy RC API. Consider enabling new API during init with use_explicit_rc_api flag");
441+
}
429442
if (this.track_domains) {
430443
log(logLevelEnums.DEBUG, "initialize, tracking domain info:[" + this.track_domains + "]");
431444
}
@@ -693,6 +706,8 @@
693706
self.ip_address = undefined;
694707
self.ignore_bots = undefined;
695708
self.force_post = undefined;
709+
self.rcAutoOptinAb = undefined;
710+
self.useExplicitRcApi = undefined;
696711
self.remote_config = undefined;
697712
self.ignore_visitor = undefined;
698713
self.require_consent = undefined;
@@ -1609,8 +1624,17 @@
16091624
* @param {function=} callback - Callback to notify with first param error and second param remote config object
16101625
* */
16111626
this.fetch_remote_config = function(keys, omit_keys, callback) {
1612-
log(logLevelEnums.INFO, "fetch_remote_config, Fetching remote config");
1613-
fetch_remote_config_v2(keys, omit_keys, 1, "legacy", callback);
1627+
// use new RC API
1628+
if (this.useExplicitRcApi) {
1629+
log(logLevelEnums.INFO, "fetch_remote_config, Fetching remote config");
1630+
// opt in is true(1) or false(0)
1631+
var opt = this.rcAutoOptinAb ? 1 : 0;
1632+
fetch_remote_config_explicit(keys, omit_keys, opt, callback);
1633+
return;
1634+
}
1635+
1636+
log(logLevelEnums.WARNING, "fetch_remote_config, Fetching remote config, with legacy API");
1637+
fetch_remote_config_explicit(keys, omit_keys, "legacy", callback);
16141638
};
16151639

16161640
/**
@@ -1621,8 +1645,8 @@
16211645
* @param {string=} api - which API to use, if not provided would use default ("legacy" is for method="fetch_remote_config", default is method="rc")
16221646
* @param {function=} callback - Callback to notify with first param error and second param remote config object
16231647
* */
1624-
function fetch_remote_config_v2(keys, omit_keys, optIn, api, callback) {
1625-
log(logLevelEnums.INFO, "fetch_remote_config_v2, Fetching remote config");
1648+
function fetch_remote_config_explicit(keys, omit_keys, optIn, api, callback) {
1649+
log(logLevelEnums.INFO, "fetch_remote_config_explicit, Fetching sequence initiated");
16261650
var request = {
16271651
method: "rc"
16281652
};
@@ -1653,14 +1677,14 @@
16531677
provivedCall = arguments[j];
16541678
}
16551679
}
1656-
if (this.check_consent(featureEnums.SESSIONS)) {
1680+
if (self.check_consent(featureEnums.SESSIONS)) {
16571681
request.metrics = JSON.stringify(getMetrics());
16581682
}
1659-
if (this.check_consent(featureEnums.REMOTE_CONFIG)) {
1683+
if (self.check_consent(featureEnums.REMOTE_CONFIG)) {
16601684
prepareRequest(request);
1661-
sendXmlHttpRequest("fetch_remote_config_v2", this.url + readPath, request, function(err, params, responseText) {
1685+
sendXmlHttpRequest("fetch_remote_config_explicit", self.url + readPath, request, function(err, params, responseText) {
16621686
if (err) {
1663-
log(logLevelEnums.ERROR, "fetch_remote_config_v2, An error occurred: " + err);
1687+
log(logLevelEnums.ERROR, "fetch_remote_config_explicit, An error occurred: " + err);
16641688
return;
16651689
}
16661690
try {
@@ -1678,17 +1702,17 @@
16781702
setValueInStorage("cly_remote_configs", remoteConfigs);
16791703
}
16801704
catch (ex) {
1681-
log(logLevelEnums.ERROR, "fetch_remote_config_v2, Had an issue while parsing the response: " + ex);
1705+
log(logLevelEnums.ERROR, "fetch_remote_config_explicit, Had an issue while parsing the response: " + ex);
16821706
}
16831707
if (provivedCall) {
1684-
log(logLevelEnums.INFO, "fetch_remote_config_v2, Callback function is provided");
1708+
log(logLevelEnums.INFO, "fetch_remote_config_explicit, Callback function is provided");
16851709
provivedCall(err, remoteConfigs);
16861710
}
16871711
// JSON array can pass
16881712
}, true);
16891713
}
16901714
else {
1691-
log(logLevelEnums.ERROR, "fetch_remote_config_v2, Remote config requires explicit consent");
1715+
log(logLevelEnums.ERROR, "fetch_remote_config_explicit, Remote config requires explicit consent");
16921716
if (provivedCall) {
16931717
provivedCall(new Error("Remote config requires explicit consent"), remoteConfigs);
16941718
}
@@ -1699,32 +1723,32 @@
16991723
* AB testing key provider, opts the user in for the selected keys
17001724
* @param {array=} keys - Array of keys opt in FOR
17011725
* */
1702-
function optAB(keys) {
1703-
log(logLevelEnums.INFO, "optAB, Providing AB test keys to opt in for");
1726+
this.enrollUserToAb = function(keys) {
1727+
log(logLevelEnums.INFO, "enrollUserToAb, Providing AB test keys to opt in for");
17041728
if (!keys || !Array.isArray(keys) || keys.length === 0) {
1705-
log(logLevelEnums.ERROR, "optAB, No keys provided");
1729+
log(logLevelEnums.ERROR, "enrollUserToAb, No keys provided");
17061730
return;
17071731
}
17081732
var request = {
17091733
method: "ab",
17101734
keys: JSON.stringify(keys)
17111735
};
17121736
prepareRequest(request);
1713-
sendXmlHttpRequest("optAB", this.url + readPath, request, function(err, params, responseText) {
1737+
sendXmlHttpRequest("enrollUserToAb", this.url + readPath, request, function(err, params, responseText) {
17141738
if (err) {
1715-
log(logLevelEnums.ERROR, "optAB, An error occurred: " + err);
1739+
log(logLevelEnums.ERROR, "enrollUserToAb, An error occurred: " + err);
17161740
return;
17171741
}
17181742
try {
17191743
var resp = JSON.parse(responseText);
1720-
log(logLevelEnums.DEBUG, "optAB, Parsed the response's result: [" + resp.result + "]");
1744+
log(logLevelEnums.DEBUG, "enrollUserToAb, Parsed the response's result: [" + resp.result + "]");
17211745
}
17221746
catch (ex) {
1723-
log(logLevelEnums.ERROR, "optAB, Had an issue while parsing the response: " + ex);
1747+
log(logLevelEnums.ERROR, "enrollUserToAb, Had an issue while parsing the response: " + ex);
17241748
}
17251749
// JSON array can pass
17261750
}, true);
1727-
}
1751+
};
17281752

17291753
/**
17301754
* Gets remote config object (all key/value pairs) or specific value for provided key from the storage
@@ -4352,6 +4376,8 @@
43524376
* @param {number} [conf.max_stack_trace_line_length=200] - maximum amount of characters are allowed per stack trace line. This limits also the crash message length
43534377
* @param {array=} conf.ignore_referrers - array with referrers to ignore
43544378
* @param {boolean} [conf.ignore_prefetch=true] - ignore prefetching and pre rendering from counting as real website visits
4379+
* @param {boolean} [conf.rc_automatic_optin_for_ab=true] - opts in the user for A/B testing while fetching the remote config (if true)
4380+
* @param {boolean} [conf.use_explicit_rc_api=false] - set it to true to use the new remote config API
43554381
* @param {boolean} [conf.force_post=false] - force using post method for all requests
43564382
* @param {boolean} [conf.ignore_visitor=false] - ignore this current visitor
43574383
* @param {boolean} [conf.require_consent=false] - Pass true if you are implementing GDPR compatible consent management. It would prevent running any functionality without proper consent

0 commit comments

Comments
 (0)