Skip to content

Instantly share code, notes, and snippets.

@thegreekjester
Last active September 17, 2021 18:52
Show Gist options
  • Save thegreekjester/f4a4fd56732f8657e80d0fecd24505fd to your computer and use it in GitHub Desktop.
Save thegreekjester/f4a4fd56732f8657e80d0fecd24505fd to your computer and use it in GitHub Desktop.
Bucketing script given input CSV
/*
Install required libraries:
- yargs (CLI)
- fast-csv (csv parser and writer)
- @optimizely/optimizely-sdk (optimizely SDK)
The following script takes in the following CLI arguments:
sdkKey (str): SDK Key of Optimizely datafile you wish to use
csv_file_path (str): The input CSV relative path with the following columns --> "User Identifier", "Bucketing ID",
"Flag Key", "List of Attributes" (optional)
new_csv_name (str): Name of output CSV (put in the current directory), defaults to "new.csv" if not provided
** All the column dtypes are strings, the "List of Attributes" has the following syntax: attribute_name=attribute_value, ...etc **
Example input CSV below (created in my own project with "allowed" and "geo" as my attribute names):
,User Identifier,Bucketing ID,Flag Key,List of Attributes,,
,Peter,A,peters_first_flag,"allowed=true,geo=USA",,
,PeterHelloeee,B,peters_first_flag,allowed=true,,
,PeterGoodbyeeee,B,peters_first_flag,"allowed=true,geo=USA",,
,PeterHelloGoodbye,A,peters_first_flag,"allowed=false,geo=USA",,
Return of this script is an output CSV with set name in the working directory the following
columns: "User Identifer", "Enabled", "Rule Used", "Variation"
Example use: node bucketing_fn.js --sdkKey 4fqCbwtL7dfarbgYxACv5 --csv_file_path example.csv --new_csv_name output.csv
*/
const yargs = require('yargs/yargs')
const { hideBin } = require('yargs/helpers')
const argv = yargs(hideBin(process.argv)).argv
const fs = require('fs');
const path = require('path');
const csv = require('fast-csv');
const { writeToPath } = require('@fast-csv/format');
const optimizely = require('@optimizely/optimizely-sdk');
const optimizelyOptions = require('@optimizely/optimizely-sdk').OptimizelyDecideOption;
var data = []
console.log('Reading in CSV from the following relative filepath ' + argv.csv_file_path + "....")
fs.createReadStream(path.resolve(__dirname, argv.csv_file_path))
.pipe(csv.parse({ headers: true, ignoreEmpty: true, trim: true }))
.on('error', error => console.error(error))
.on('data', row => data.push(row))
.on('end', _ => get_bucketing_decisions(data));
function isInt(value) {
if (isNaN(value)) {
return false;
}
var x = parseFloat(value);
return (x | 0) === x;
}
function set_converted_attributes(attributes, user){
if(!attributes.length){
return
}
var attributes_arr = attributes.split(',')
attributes_arr.forEach(function(attr){
let name, value, final_value
[name, value] = attr.split('=')
switch (value){
case 'true':
final_value = Boolean(value)
break;
case 'false':
final_value = Boolean(value)
break;
case isInt(value):
final_value = parseInt(value)
break;
default:
final_value = value
break;
}
user.setAttribute(name, final_value)
})
}
function get_bucketing_decisions(data){
// Instantiating the client
const client = optimizely.createInstance({
sdkKey: argv.sdkKey, // Provide the sdkKey of your desired environment here
});
client.onReady().then(() => {
console.log("Client with the following SDK Key" + argv.sdkKey + " is ready...")
new_rows = []
data.forEach(function(row){
let decisionObj;
let user = client.createUserContext(row['User Identifier']);
if('List of Attributes' in row){
set_converted_attributes(row['List of Attributes'], user)
}
const _bucketing_id = row['Bucketing ID'];
if (_bucketing_id) {
user.setAttribute('$opt_bucketing_id', row['Bucketing ID'])
}
decisionObj = user.decide(row['Flag Key'], [optimizelyOptions.DISABLE_DECISION_EVENT])
new_rows.push({"User Identifier":decisionObj.userContext.getUserId(), "Enabled":decisionObj.enabled,
"Rule Used":decisionObj.ruleKey, "Variation":decisionObj.variationKey})
})
let csv_name = argv.new_csv_name || 'new.csv'
writeToPath(path.resolve(__dirname, csv_name), new_rows, {headers:true})
.on('error', err => console.error(err))
.on('finish', () => process.exit());
})
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment