ShoppingGives SDK

The ShoppingGives SDK (SG SDK) provides the necessary methods for developing custom experiences by facilitating the development of custom widgets or UI components built by our clients using any Javascript-based framework (such as REACT, Angular, or Vue). The SG SDK provides the data needed to power a custom UI. This SG SDK does not provide UI elements, only the data needed to power a custom UI.

Built With

Prerequisites

To use the SG SDK, you will need a ShoppingGives store ID (contact your ShoppingGives account manager).

Getting Started

Installation

npm install @shoppinggivesos/impact-sdk

Usage

The first thing you need to do after installing the package is select the type of "context" you want to set up. We currently support two types of context: Cart and Product. If you plan to use the SG SDK to power a custom experience on the product page, then you need to use the ProductHandler. Likewise, if you plan to power a custom experience on the cart page, use the CartHandler.

import { CartHandler, Environments } from '@shoppinggivesos/impact-sdk';

const config = {
    storeId: '00000000-0000-0000-0000-000000000000', // Shoppinggives store ID
    environment: Environments.Production, // Shoppinggives store environment for most people 
                                          // you will select Environments.Production here.
                                          // If you receive a Staging store ID from your account manager, 
                                          // use the Environments.Staging value
    testMode: false, // Sets the tracking to be test purchases that do not create a real donation!
    logger: {
        error: (message) => {},
        debug: (message) => {},
        warn: (message) => {},
    }, // Optional: Custom logging implementation, 
       // if you omit this param the SG SDK uses console.log by default.
    persistence: {
        get: (key) => {},
        set: (key, value) => {},
        delete: (key) => {},
    }, // Optional: Custom persistence cache implementation,
       // if you omit this param the SG SDK uses session storage by default.
};

// bootstrap the client
const client = new CartHandler(config);

// register any events if you want to use the event system vs 
// async / awaiting the methods. (more information can be found below)
// events need to be registered before the initialize method is called.
client.on('SDK::Ready', (data) => {
    // handle SDK::Ready event
});

// initialize the client with current cart state
const data = await client.initialize({
    cartTotal: 10, // Current cart total
    lineItems: [], // All current line items in the cart or an empty array if no items are in the cart.
    discount: 0, // The discount applied to the cart if any is set. This is the $ amount 
                 // not the % percentage.
});

Handling Updates

We support two main ways to work with the SG SDK.

  1. All public-facing methods return promises so that you can use async / await or then / catch to retrieve the returned data. For example:

async / await

const results = await client.search('Happys Porch', 0, 25);

then / catch

let results = []; 
client
  .search('Homes For Our Troops', 0, 25)
  .then((data) => {
     results = data;
  })
  .catch((error) => {});
  1. Alternatively, we have an events system. You can subscribe to the events and handle changes with callback functions.
Event TypeDescription
SDK::ReadyEmitted when the SG SDK has completed all necessary initialization steps and is ready to accept requests from the client. This typically includes loading any necessary resources and establishing a connection to the server.
SDK::ErrorEmitted when an error occurs inside the SG SDK, it contains a type property that dictates the type of error so you can handle it accordingly.
SDK::UpdatedEmitted when the SG SDK has finished re-calculating the donation based on the new data.
Cause::UpdatedEmitted when our backend has confirmed the new cause was successfully updated.
Search::FinishedEmitted when the call to the search ShoppingGives API is finished.

Example:

client.on('Cause::Updated', (data) => {
    // handle the updating of the selected cause
});

Handling Errors

We provide two systems for dealing with errors in the SG SDK. By default, the SG SDK will throw an error you must catch. The other way you can handle errors is by using the SDK::Error event and set up a callback to handle errors in a centralized place.

The error payload includes a 'type' property that specifies the type of error that occurred. This can be used to distinguish between different types of errors and to tailor your error-handling logic accordingly.

try {
    results = await client.search(searchTerm, 0, 25);
} catch (error) {
    // handle error based on the type property:
    switch (error.type) {
      case "ShoppinggivesApiError":
        // handle error, hide UI or show error state
        break;
      case "ShoppinggivesValidationError"
        // handle validation error
      default:
        break;
    }
}

Alternatively, you can handle errors by subscribing to the event SDK::Error, the event is emitted whenever an error occurs inside the SG SDK. This event is intended to provide a mechanism for handling errors that may occur while using the SG SDK so that you can gracefully handle or recover from them in your code.

To handle this event, you can add an event listener that gets called whenever the event is emitted. The event listener function should accept an 'error' parameter containing an instance of an error object with additional information about the error.

Here is an example of how you might handle the SDK::Error event:

client.on('SDK::Error', (error) => {
  switch (error.type) {
    case "ShoppinggivesApiError":
      // handle error, hide UI or show error state
      break;
    case "ShoppinggivesValidationError"
      // handle validation error
    default:
      break;
  }
});

Methods

Initialize() Product Handler

This function must be called first to initialize the product widget. The response contains everything needed to load the product widget.

Request Body:

ParameterTypeRequiredDescription
cmsIdstringtrueProduct CMS ID
pricenumbertrueProduct price

Response Body:

PropertyTypeDescription
totalDonationAmountnumberCurrent total donation amount to display on the widget
showWidgetbooleanWhether or not to show the widget based on store settings or eligibility
donationBreakdownDonationRecipientsModel[]The complete breakdown of causes and their associated donation
charitiesCauseModel[]Charities associated with the store
selectedCausesCauseModel[]Currently selected causes for donation
activeCampaignsActiveCampaignsModelActive campaigns on store
searchEnabledbooleanWhether the store has search toggled on or off
letShoppersChoosebooleanWhether the customer has a choice of charities
trackingIdstringID associating supported charity to the user session

Update() Product Handler

Re-calculates the donation amount based on product changes, i.e., product variant changes.
Request Body:

ParameterTypeRequiredDescription
cmsIdstringtrueProduct CMS ID
pricenumbertrueProduct price

Response Body:

PropertyTypeDescription
totalDonationAmountnumberCurrent total donation amount to display on the widget
donationBreakdownDonationRecipientsModel[]The complete breakdown of causes and their associated donation
charitiesCauseModel[]Charities associated with the store
selectedCausesCauseModel[]Currently selected causes for donation
excludedbooleanWhether or not the product is excluded from the donation

Initalize() Cart Handler

This function must be called first to initialize the cart widget. The response contains everything needed to load the cart widget.

Request Body:

ParameterTypeRequiredDescription
lineItemsCmsLineItem[]trueAll line items in the cart
discountnumberfalseCurrent cart discount

Response Body:

PropertyTypeDescription
totalDonationAmountnumberCurrent total donation amount to display on the widget
showWidgetbooleanWhether or not to show the widget based on store settings or eligibility
donationBreakdownDonationRecipientsModel[]The complete breakdown of causes and their associated donation
charitiesCauseModel[]Charities associated with the store
selectedCausesCauseModel[]Currently selected causes for donation
activeCampaignsActiveCampaignsModelActive campaigns on store
searchEnabledbooleanWhether the store has search toggled on or off
letShoppersChoosebooleanWhether the customer has a choice of charities
trackingIdstringID associating supported charity to the user session
directDonationInCartbooleanWhether or not there is a direct donation on the cart (roundups/addons)

Update() Cart Handler

Re-calculates the donation amount based on the cart's item changes.

Request Body:

ParameterTypeRequiredDescription
lineItemsCmsLineItem[]trueAll line items in the cart
discountnumberfalseCurrent cart discount

Response Body:

PropertyTypeDescription
totalDonationAmountnumberCurrent total donation amount to display on the widget
donationBreakdownDonationRecipientsModel[]The complete breakdown of causes and their associated donation
charitiesarray[]Charities associated with the store
selectedCausesCauseModel[]Currently selected causes for donation
directDonationInCartbooleanWhether or not there is a direct donation on the cart (roundups/addon)

Search()

Returns a list of charities based on search parameters.

Request Body:

ParameterTypeRequired
skipnumbertrueHow many entries to skip
takenumbertrueHow many entries to take
searchTermstringflaseString being searched
zipstringfalseSearch within a ZIP code
citystringfalseSearch within a city
statestringfalseSearch within a state (Value is the 2 letter state abbreviation)
categorystringfalseSearch within a category Category Dictionary[]

Response Body:

CharityResponseModel[]

SetCause()

Updates tracking when a user selects a new cause.

Request Body:

ParameterTypeRequiredDescription
causeCauseModel[]trueSelected cause

Response Body:

PropertyTypeDescription
causeCauseModel[]Selected cause
newTotalDonationnumberThe current total donation amount for the selected cause could potentially have a multiplier

Models

CmsLineItem

export interface ICmsLineItem {
  id: any;
  price: number;
  quantity: number;
  discount: number;
}

DonationRecipient

export interface IDonationRecipient {
  id: string;
  isPortfolio: boolean;
  donation: number;
  logoUrl: string;
  name: string;
  description: string;
  directDonation: string;
  bannerUrl?: string;
  city?: string;
  state?: string;
  streetAddress?: string;
  zip?: number;
  donationBreakdown?: object; // dictionary
}

CauseModel

export class CauseModel {
  isPortfolio: boolean;
  id: any;
  name: string;
  website: string;
  logoUrl: string;
  streetAddress: string;
  city: string;
  state: string;
  zip: number;
  description: string;
  multiplier?: number;
  categoryId?: number;
  categoryName?: string;
  categoryLogoUrl?: string;
  headline?: string;
  bannerUrl?: string;
  portfolioCharities?: any[];
  default: boolean;
}

ActiveCampaignsModel

export class ActiveCampaignsModel {
  onlinePurchase: boolean;
  yotpoRedemption: boolean;
  roundUpDonation: boolean;
  addOnDonation: boolean;
  pointOfSale: boolean;
  postPurchaseDonation: boolean;
  roundUpPos: boolean;
} 

CharityResponseModel

export class CharityResponseModel {
    id: number;
    name: string;
    website: string;
    logoUrl: string;
    streetAddress: string;
    city: string;
    state: string;
    zip: number;
    description: string;
    categoryId: number;
    categoryName: string;
    categoryLogoUrl: string;
    nteeFullCode: string;
    nteeMainCode: number;
    nteeSubCode: number;
}

Category Dictionary

Categories = [
    { value: 0, label: 'Art and Culture' },
    { value: 1, label: 'Education' },
    { value: 2, label: 'Environment' },
    { value: 3, label: 'Animal Protection and Services' },
    { value: 4, label: 'Health' },
    { value: 5, label: 'Mental Health and Rehabilitation' },
    { value: 6, label: 'Disease and Disorder' },
    { value: 7, label: 'Medical Research' },
    { value: 8, label: 'Criminal Justice and Legal' },
    { value: 9, label: 'Employment' },
    { value: 10, label: 'Food and Nutrition' },
    { value: 11, label: 'Housing and Shelters' },
    { value: 12, label: 'Public Safety' },
    { value: 13, label: 'Sports' },
    { value: 14, label: 'Youth Development' },
    { value: 15, label: 'Human Services' },
    { value: 16, label: 'International Affairs' },
    { value: 17, label: 'Civil Rights' },
    { value: 18, label: 'Community' },
    { value: 19, label: 'Philanthropy and Volunteering' },
    { value: 20, label: 'Science and Tech' },
    { value: 21, label: 'Social Science' },
    { value: 22, label: 'Public Benefits' },
    { value: 23, label: 'Religion' },
    { value: 24, label: 'Mutual Benefit Organizations' },
    { value: 25, label: 'Other' },
]