npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

yield-siftscience

v0.2.1

Published

Promise-wrapped Sift Science lib for yielding. Also supports regular callback functions.

Downloads

589

Readme

Yield Sift Science - NodeJS

A promise-wrapped helper lib for yielding Sift Science API calls in nodejs.

Also supports regular callbacks.

Table of contents:

INSTALLATION

Using npm:

$ npm install yield-siftscience

USAGE

Require with API Key:

var siftscience = require('yield-siftscience')({
  api_key: 'YOUR_SIFT_SCIENCE_REST_API_KEY'
});

Available Options:

  • {string} api_key (get your api key)
  • {string} [account_id] (required for device fingerprinting api, get your account id)
  • {string} [partner_id] (required for partner api, get your partner id)
  • {string[]} [custom_events] (ex: ['referral_code_redeemed', 'contacted_customer_support', ...])
  • {function} [global_callback] (ex: function(err, response) { ... } - can be used to override promise and make regular callback on all requests)
  • {string[]} [abuse_types] (default: [] - specify an array of sift science products. This parameter restricts the list of score or workflow decision retrieved to the specific products requested. more info. Possible values: Array with one or more of - ['payment_abuse','promo_abuse','content_abuse','account_abuse','legacy'])
  • {boolean} [return_score] (default: false - can be used to return score from sift science synchronously more info)
  • {boolean} [return_workflow_status] (default: false - can be used to return workflow status from sift science synchronously more info)
  • {object} [webhooks] (default: {} - see webhooks for usage)
  • {boolean} [return_action] DEPRECATED (default: false - can be used to get extra params from sift science responses more info)

Note: In v204 of the sift science API, return_action is deprecated in favor of the more granular combined use of abuse_types, return_score and return_workflow_status flags. more info

EVENTS API

https://siftscience.com/developers/docs/curl/events-api

Send Event:

var result = yield siftscience.event.create_account({
  '$session_id': session.id,
  '$user_id':    user.id,
  '$user_email': user.email
});
var result = yield siftscience.event.login({
  '$session_id':   session.id,
  '$user_id':      user.id,
  '$login_status': siftscience.CONSTANTS.STATUS.SUCCESS
});

Send Generic Custom Event:

var result = yield siftscience.event.custom_event('referral_code_redeemed', {
  '$session_id': session.id,
  '$user_id':    user.id,
  'code':        'abc123'
});
var result = yield siftscience.event.custom_event('contacted_customer_support', {
  '$session_id': session.id,
  '$user_id':    user.id
});

Inject Custom Events:

Optionally, you can pass in an array of custom event names to add to the lib

var siftscience = require('yield-siftscience')({
  api_key:       'YOUR_SIFT_SCIENCE_REST_API_KEY',
  custom_events: ['referral_code_redeemed', 'contacted_customer_support', ...]
});

Then you could use

var result = yield siftscience.event.referral_code_redeemed({
  '$session_id': session.id,
  '$user_id':    user.id,
  'code':        'abc123'
});
var result = yield siftscience.event.contacted_customer_support({
  '$session_id': session.id,
  '$user_id':    user.id,
});

LABELS API

https://siftscience.com/developers/docs/curl/labels-api

Send Label:

var result = yield siftscience.label(user.id, {
  '$is_bad':      true,
  '$abuse_type':  siftscience.CONSTANTS.ABUSE_TYPE.PAYMENT_ABUSE,
  '$description': 'Because they are spamming and abusing our system',
  '$source':      'manual review',
  '$analyst':     '[email protected]'
});

Remove Label:

var result = yield siftscience.unlabel(user.id);

DECISION API

https://siftscience.com/developers/docs/curl/decisions-api

Get decision status:

var result = yield siftscience.decision.status(siftscience.CONSTANTS.ENTITY_TYPE.USERS, entity.id)

List decisions:

var result = yield siftscience.decision.list(siftscience.CONSTANTS.ENTITY_TYPE.USER)

Apply decision to user:

var result = yield siftscience.decision.apply(user.id, null, {
  'decision_id': 'user_looks_ok_payment_abuse',
  'source':      siftscience.CONSTANTS.DECISION_SOURCE.MANUAL_REVIEW,
  'analyst':     '[email protected]',
  'description': 'applied via the high priority queue, queued user because their risk score exceeded 85'
})

Apply decision to order:

var result = yield siftscience.decision.apply(user.id, order.id, {
  'decision_id': 'user_looks_ok_payment_abuse',
  'source':      siftscience.CONSTANTS.DECISION_SOURCE.AUTOMATED_RULE,
  'description': 'Auto block pending order as score exceeded risk threshold of 90'
})

WORKFLOW API

https://siftscience.com/developers/docs/curl/workflows-api

Get workflow status:

var result = yield siftscience.workflow.status(workflow.id)

SCORE API

https://siftscience.com/developers/docs/curl/score-api

Get Score:

var result = yield siftscience.score(user.id);

DEVICE FINGERPRINTING API

https://siftscience.com/developers/docs/curl/device-fingerprinting-api

JavaScript Snippet:

https://siftscience.com/developers/docs/javascript/javascript-api

Install the following JavaScript snippet on every public-facing page on your site. Do not include this snippet on internal tools or administration systems.

Replace 'UNIQUE_SESSION_ID', 'UNIQUE_USER_ID', and 'INSERT_JS_SNIPPET_KEY_HERE' with proper values

<script type="text/javascript">
  var _user_id = 'UNIQUE_USER_ID';
  var _session_id = 'UNIQUE_SESSION_ID';

  var _sift = window._sift = window._sift || [];
  _sift.push(['_setAccount', 'INSERT_JS_SNIPPET_KEY_HERE']);
  _sift.push(['_setUserId', _user_id]);
  _sift.push(['_setSessionId', _session_id]);
  _sift.push(['_trackPageview']);

  (function() {
    function ls() {
      var e = document.createElement('script');
      e.src = 'https://cdn.siftscience.com/s.js';
      document.body.appendChild(e);
    }
    if (window.attachEvent) {
      window.attachEvent('onload', ls);
    } else {
      window.addEventListener('load', ls, false);
    }
  })();
</script>

Init with Account ID:

An Account ID is required to use the fingerprint api. Get your Account ID

var siftscience = require('yield-siftscience')({
  api_key:    'YOUR_SIFT_SCIENCE_REST_API_KEY',
  account_id: 'YOUR_SIFT_SCIENCE_ACCOUNT_ID'
});

Get Session:

var result = yield siftscience.fingerprint.get_session(session.id);

Get Device:

var result = yield siftscience.fingerprint.get_device(device_fingerprint);

Label Device:

var result = yield siftscience.fingerprint.label_device(device_fingerprint, siftscience.CONSTANTS.DEVICE_LABEL.BAD);

Get Devices:

var result = yield siftscience.fingerprint.get_devices(user.id);

PARTNER API

https://siftscience.com/developers/docs/curl/partner-api

NOTE: I have not tested these as I do not have a partner account with sift science. Please report any bugs.

Init with Account ID and Partner ID (they may be the same thing, I'm not sure):

An Account & Partner ID are required to use the partner api. Get your Account & Partner ID

var siftscience = require('yield-siftscience')({
  api_key:    'YOUR_SIFT_SCIENCE_REST_API_KEY',
  account_id: 'YOUR_SIFT_SCIENCE_ACCOUNT_ID',
  partner_id: 'YOUR_SIFT_SCIENCE_PARTNER_ID'
});

Create Account:

var result = yield siftscience.partner.create_account({
  site_url:      'merchant123.com',
  site_email:    '[email protected]',
  analyst_email: '[email protected]',
  password:      's0mepA55word'
});

List Accounts:

var result = yield siftscience.partner.list_accounts();

Configure Notifications:

var result = yield siftscience.partner.configure_notifications({
  email_notification_threshold: 0.5,
  http_notification_threshold:  0.5,
  http_notification_url:       'https://api.partner.com/notify?account=%s'
});

CALLBACKS

Don't know what yielding or promising is? All calls support regular callbacks:

siftscience.score(user.id, function(_err, _response) {
  if (_err) {
    console.log(_err);
  }
  else {
    var score = _response.body;
    console.log(score);
  }
});

You can also inject a global callback for all requests:

var siftscience = require('yield-siftscience')({
  api_key:         'YOUR_SIFT_SCIENCE_REST_API_KEY',
  global_callback: function(_err, _response) {
    if (_err) {
      console.log(_err);
    }
    else {
      var result = _response.body;
      console.log(result);
    }
  }
});

CONSTANTS

siftscience.CONSTANTS = {
  SHIPPING_METHOD: {
    ELECTRONIC: '$electronic',
    PHYSICAL:   '$physical'
  },
  TRANSACTION_TYPE: {
    SALE:       '$sale',
    AUTHORIZE:  '$authorize',
    CAPTURE:    '$capture',
    VOID:       '$void',
    REFUND:     '$refund',
    DEPOSIT:    '$deposit',
    WITHDRAWAL: '$withdrawal',
    TRANSFER:   '$transfer'
  },
  STATUS: {
    SUCCESS: '$success',
    FAILURE: '$failure',
    PENDING: '$pending'
  },
  FAILURE_REASON: {
    ALREADY_USED:   '$already_used',
    INVALID_CODE:   '$invalid_code',
    NOT_APPLICABLE: '$not_applicable',
    EXPIRED:        '$expired'
  },
  SOCIAL_SIGN_ON_TYPE: {
    FACEBOOK: '$facebook',
    GOOGLE:   '$google',
    YAHOO:    '$yahoo',
    TWITTER:  '$twitter',
    OTHER:    '$other',
    LINKEDIN: '$linkedin'
  },
  CONTENT_STATUS: {
    DRAFT:              '$draft',
    PENDING:            '$pending',
    ACTIVE:             '$active',
    PAUSED:             '$paused',
    DELETED_BY_USER:    '$deleted_by_user',
    DELETED_BY_COMPANY: '$deleted_by_company'
  },
  CHARGEBACK_STATE: {
    RECEIVED: '$received',
    ACCEPTED: '$accepted',
    DISPUTED: '$disputed',
    WON:      '$won',
    LOST:     '$lost'
  },
  CHARGEBACK_REASON: {
    FRAUD:                '$fraud',
    DUPLICATE:            '$duplicate',
    PRODUCT_NOT_RECEIVED: '$product_not_received',
    PRODUCT_UNACCEPTABLE: '$product_unacceptable',
    OTHER:                '$other'
  },
  ORDER_STATUS: {
    APPROVED:  '$approved',
    CANCELED:  '$canceled',
    HELD:      '$held',
    FULFILLED: '$fulfilled',
    RETURNED:  '$returned'
  },
  ORDER_CANCEL_REASON: {
    PAYMENT_RISK: '$payment_risk',
    ABUSE:        '$abuse',
    POLICY:       '$policy',
    OTHER:        '$other'
  },
  ORDER_STATUS_SOURCE: {
    AUTOMATED: '$automated',
    MANUAL_REVIEW: '$manual_review'
  },
  VERIFICATION_TYPE: {
    SMS:        '$sms',
    PHONE_CALL: '$phone_call',
    EMAIL:      '$email',
    APP_TFA:    '$app_tfa',
    CAPTCHA:    '$captcha'
  },
  PAYMENT_TYPE: {
    CASH:                     '$cash',
    CHECK:                    '$check',
    CREDIT_CARD:              '$credit_card',
    CRYPTO_CURRENCY:          '$crypto_currency',
    DIGITAL_WALLET:           '$digital_wallet',
    ELECTRONIC_FUND_TRANSFER: '$electronic_fund_transfer',
    FINANCING:                '$financing',
    GIFT_CARD:                '$gift_card',
    INTERAC:                  '$interac', // Deprecated?
    INVOICE:                  '$invoice',
    MONEY_ORDER:              '$money_order',
    MASTERPASS:               '$masterpass', // Deprecated?
    POINTS:                   '$points',
    STORE_CREDIT:             '$store_credit',
    THIRD_PARTY_PROCESSOR:    '$third_party_processor',
    VOUCHER:                  '$voucher'
  },
  RESPONSE_STATUS_MESSAGE: {
    '-4':  'Service currently unavailable. Please try again later.',
    '-3':  'Server-side timeout processing request. Please try again later.',
    '-2':  'Unexpected server-side error',
    '-1':  'Unexpected server-side error',
    '0':   'Success',
    '51':  'Invalid API key',
    '52':  'Invalid characters in field name',
    '53':  'Invalid characters in field value',
    '54':  'Specified user_id has no scoreable events',
    '55':  'Missing required field',
    '56':  'Invalid JSON in request',
    '57':  'Invalid HTTP body',
    '60':  'Rate limited',
    '104': 'Invalid API version',
    '105': 'Not a valid reserved field',
    '111': 'This feature is not enabled in your feature plan.'
  },
  REASON: {
    CHARGEBACK:        '$chargeback',
    SPAM:              '$spam',
    FUNNELING:         '$funneling',
    FAKE:              '$fake',
    REFERRAL:          '$referral',
    DUPLICATE_ACCOUNT: '$duplicate_account'
  },
  DEVICE_LABEL: {
    BAD:     'bad',
    NOT_BAD: 'not_bad'
  },
  DEVICE_PERVASIVENESS: {
    LOW:    'low',
    MEDIUM: 'medium',
    HIGH:   'high'
  },
  ABUSE_TYPE: {
    PAYMENT_ABUSE:   'payment_abuse',
    CONTENT_ABUSE:   'content_abuse',
    PROMOTION_ABUSE: 'promotion_abuse',
    PROMO_ABUSE:     'promo_abuse',
    ACCOUNT_ABUSE:   'account_abuse',
    LEGACY:          'legacy'
  },
  DECISION: {
    PAYMENT_ABUSE:   'payment_abuse',
    PROMOTION_ABUSE: 'promotion_abuse',
    PROMO_ABUSE:     'promo_abuse',
    CONTENT_ABUSE:   'content_abuse',
    ACCOUNT_ABUSE:   'account_abuse',
    LEGACY:          'legacy'
  },
  DECISION_CATEGORY: {
    BLOCK:  'BLOCK',
    WATCH:  'WATCH',
    ACCEPT: 'ACCEPT'
  },
  DECISION_SOURCE: {
    MANUAL_REVIEW:  'MANUAL_REVIEW',
    AUTOMATED_RULE: 'AUTOMATED_RULE',
    CHARGEBACK:     'CHARGEBACK'
  },
  STATE: {
    RUNNING:  'running',
    FINISHED: 'finished',
    FAILED:   'failed'
  },
  ENTITY_TYPE: {
    USERS:  'users',
    ORDERS: 'orders',
    USER:   'user',
    ORDER:  'order'
  },
  APP: {
    DECISION:        'decision',
    REVIEW_QUEUE:    'review_queue',
    USER_SCORER:     'user_scorer',
    ORDER_SCORER:    'order_scorer',
    EVENT_PROCESSOR: 'event_processor'
  },
  ACCOUNT_STATE: {
    ACTIVE:   'ACTIVE',
    DISABLED: 'DISABLED',
    DELETED:  'DELETED'
  }
};

WEBHOOKS

NOTE: Currently only supports express/body-parser

Install Express/Body-Parser:

$ npm install --save express
$ npm install --save body-parser
$ npm install --save yield-siftscience

Example App:

Let's say you have created an action called "Test" with Action ID test

var express    = require('express');
var bodyParser = require('body-parser');

// Require yield-siftscience with a webhooks mapping option
var siftscience = require('yield-siftscience')({
  api_key: 'YOUR_SIFT_SCIENCE_REST_API_KEY',
  webhooks: {
    // This will receive all webhooks, regardless of Action ID
    all: function(req, res, done) {
      console.log('all: ', req.body);
      done();
    },
    // This will receive webhooks with Action ID 'test'
    test: function(req, res, done) {
      console.log('test: ', req.body);
      done();
    }
  }
});

// Set up the webhook listener
var app = express();
app.post('/siftscience', bodyParser.json(), siftscience.webhook.express());

app.listen(config.port);

SIFT SCIENCE DOCUMENTATION

https://siftscience.com/developers/docs/curl/apis-overview

TESTING

Copy Example Config:

$ cp test/config-example.js test/config.js
$ nano test/config.js

Set Sandbox API Key, JS Key, Account ID, Workflow Run ID

module.exports = {
  api_key:         'xxxxxxxxxxxxxxxx',
  js_key:          'xxxxxxxxxx',
  account_id:      'xxxxxxxxxxxxxxxxxxxxxxxx',
  workflow_run_id: 'xxxxxxxxxxxxx',
  host:            'localhost',
  port:            3000
};

Install Dependencies:

$ npm install

Run Test:

$ npm test

Visit Page:

Visiting the test web page will trigger a page view for user_id = '1' and session_id = '1'

http://localhost:3000

NOTE: You will have to run the test a second time if this is your first time visiting the test web page

CHANGE LOG

0.2.1:

  • Add support for decision list api
  • Add support for apply decision api
  • Add many missing CONSTANTS
  • Add $verification event

0.2.0:

  • Update to API v204
  • BREAKING CHANGE: siftscience.unlabel() function signature has changed to support abuse type
  • BREAKING CHANGE: siftscience.score() function signature has changed to support abuse types
  • Add support for decision status api
  • Add support for workflow status api

0.1.2:

  • Add validations for all arguments
  • Update readme with more links to source reference

0.1.1:

  • Found the return_action documentation - MORE INFO
  • Remove support for api version option - will only be supporting the most current version v203
  • Add validations for all init options

0.1.0:

  • BREAKING CHANGE: Consolidate init args into one options arg - see USAGE
  • Add support for return_action in init options - MORE INFO
  • Add support for device fingerprinting api
  • Add support for partner api - NOTE: I do not have a partner account with sift science, this is untested. Please report any bugs.
  • Add CONSTANTS object to siftscience object for things like $reasons and $shipping_method - see LABELS API
  • Add express/body-parser webhook support
  • Add a minimal test package

0.0.9:

  • Add unlabel method to siftscience object