Introducing Socket Firewall: Free, Proactive Protection for Your Software Supply Chain.Learn More
Socket
Book a DemoInstallSign in
Socket

@arc-core-components/feature_subscriptions

Package Overview
Dependencies
Maintainers
15
Versions
67
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@arc-core-components/feature_subscriptions

All subscribing, all the time.

latest
Source
npmnpm
Version
2.2.1
Version published
Maintainers
15
Created
Source

Arc Subscriptions

This is an out of the box solution for Arc Subscriptions that offers three different levels of components to suit your needs plus convenience functions.

  • SPAs - these requires only minimal style customization and configuration with the option to pass in custom localization. It includes all of the workflows pre-built into two different components for you to get up and running on Arc Subscriptions as soon as possible with minimal effort. One is designed for logging in and user profile/account management and the other allows the user to purchase products and follow the checkout and payment workflow.

    • Identity - login, lost password, verify email, profile, manage subscriptions, order history

    • Retail - offers/products, cart, payment processing, order confirmation

    • Custom SPA - shows an example of how to create your own custom SPA

  • Forms - these are pre-built forms for the different areas of Arc Subscriptions that you can highly customize or use as they are to create your own workflows or to meet the specific needs of your project.

    • Identity Forms - forms related to account creation and management, email verification and password resets

    • Retail & Sales Forms - forms offers/products and shopping cart

    • Paywall - all variations of the paywall forms and an example component

    • Custom Form - an example of how to create your own custom form

  • Elements - these are all of the form sub-components that make up Arc Subscriptions so that you can create and build your highly customizable forms and workflows to meet the specific needs of your project

  • Functions & Analytics - these are functions and events you can use to help with your custom form creations or for customizing a specific form.

    • Analytics - call these or listen to these for your analytics reporting

    • Input Validation - validations to run on various types of form inputs

    • Utilities - various other functions

Installation

Run npm i @arc-core-components/feature_subscriptions@stable to add it to your project.

In your default output file, add a script that sets window.arcIdentityApiOrigin, window.arcSalesApiOrigin, and window.arcSignInUrl. The arcIdentityApiOrigin and arcSalesApiOrigin will usually point to the same location. The arcSignInUrl should point to a page or template where you have implemented your signin feature.

For example here is a partial snippet:

// File: components/output-types/default.jsx

//set cc client side variables
let subsConfig = `window.arcIdentityApiOrigin = "YOUR_API_ORIGIN_URL";`;
subsConfig += `window.arcSalesApiOrigin = "YOUR_API_ORIGIN_URL";`;
subsConfig += `window.arcSignInUrl = "YOUR_SUBSCRIPTIONS_LOGIN_URL";`;

return (<html lang="en">
  <head>
    <script type="text/javascript" dangerouslySetInnerHTML={{ __html: subsConfig }} />
  </head>
  <body>
    ...

Identity

This allows you to use pre-built solutions for managing login/logout, lost password, user profile, viewing order history and managing subscriptions.

SPA

This is a Single Page App that has all of the pre-configured workflow already setup and ready for you to customize and start using.

PropertyTypeDescription
config (required)ObjectConfigurations for the SPA
debugBooleanToggle debugging messages inside of the SPA
localizationObjectObject with mappings to all the text, error codes and country codes so you can customize all text within the SPA
stylesObjectObject with mappings to all styles so you can customize the look and feel of the SPA

SPA Configuration

These are passed to the config property and will affect how your SPA works.

PropertyTypeDescription
dateFormatStringAccepts EU or US
useCookiesBooleanWhether or not to allow cookies (if disabled uses localstorage instead)
autoLoginBooleanIf true will automatically login after creating a new account
secondLastNameBooleanIf true, displays a second last name field on the sign up and profile form
enableMagicLinkBooleanToggles showing the magic link button on the forgot password form
recaptchaObjectDeveloper configuration settings for ReCaptcha
debugBooleanWhen true will console log debugging messages
termsUrlStringUrl to your terms of service
privacyUrlStringUrl to your privacy policy
GDPRUrlStringUrl to GDPR policies
registerUrlStringUrl to create a new account
signInUrlStringUrl to sign in
signOutUrlStringUrl to sign out page
signOutPageHomeUrlStringUrl to return to the home page once you've signed out
signOutPageSignInUrlStringUrl on the sign out page to sign in again
signOutPageSignUpUrlStringUrl on the sign out page to create a new account
profileUrlStringUrl to the user's profile page
useTermsModalBooleanIf true, shows the terms of service in a modal window rather than a clickable URL
isTermsModalOpenBooleanFunction
termsModalHideCloseIconBooleanWhether or not to hide the terms of service close modal icon
termsModalChildrenObjectContent to display in the terms of service modal
showSignOutLinkBooleanWhether or not to show the sign out link on the profile
hidePrivacyModalCloseIconBooleanWhether or not to display the close modal icon in the privacy modal
googleButtonWidthNumberThe width of the google social sign in button
googleButtonHeightNumberThe height of the google social sign in button
googleButtonLongTitleBooleanWhether or not to use the short title or the long title on the google social sign in button
googleButtonThemeStringThe theme for the google button, defaults to "dark"
fbButtonSizeStringThe size of the facebook button
fbButtonTypeStringThe type of facebook button
fbIncludePictureBooleanWhether or not to include a picture on the facebook button
dobRegistrationBooleanTurn on requirements to be a certain age before you can register
dobRequiredRegistrationBooleanForces the date of birth field to be required on the registration form
hideFacebookOnSignInBooleanHides the button to sign in with Facebook on the sign in page
hideGoogleOnSignInBooleanHides the Google sign in button on the sign in page
hideFacebookOnSignUpBooleanHides the register with Facebook button on the registration page
hideGoogleOnSignUpBooleanHides the register with Google button on the registration page
registrationAgeNumberSets the age a user must be in order to create an account, use 0 (default) if any age is allowed. For example, if this value is set to 14 then users that are 14 years and 1 day old will be permitted to register, anyone younger will not.
peekSignUpStateCallbackFunctionA function intended to return the current state values to be used in defining new logic/properties outside of the sign up form, for instance setting profile attributes from selections in the privacy modal

Hash Routes

These are the hash routes used in the Identity SPA:

#/ or #/sign-in – login to an existing account or optionally use social logins (FB or Google)

#/register – creates a new account by filling in the form or optionally using social sign up buttons (FB or Google)

#/sign-out – destroys the user’s session and gives them options on where to go next

#/profile – Includes the change password form, allows the user to edit their account information they entered when they signed up, includes the privacy modal (if enabled) and a link to sign out.

#/manage – allows a user to manage their current, update their credit card, change their billing address, cancel a subscription and view their order history.

#/forgot-password – for users who have forgotten their password.

#/verify-email?nonce={nonce} – if enabled in the subs admin, will force users to verify their email address before they can proceed to their profile page.

#/reset-password?nonce={nonce} - allows the user to reset their password if the nonce is valid.

#/magic-link?nonce={nonce} – allows the user to send themselves a one-time access link to login without having to remember their password if the nonce is valid.

SPA Sample Implementation

/* eslint-disable */
import React from 'react';
import Subscriptions from '@arc-core-components/feature_subscriptions';

/**
* @class IdentitySPA
* @desc Single page application for subscriptions Sign In, Sign Up, Profile,
* Reset Password, and Magic Link functionality
*
* @return {Object} IdentitySPA
*/
class Identity extends React.PureComponent {

  /**
  * Render the Identity SPA
  **/
  render() {
    return (<Subscriptions.IdentitySPA
      debug={false}
      styles={{
        wrapperClasses: 'col',
        profilePageContainerClasses: 'width_full',
        managePageContainerClasses: 'width_full',
        headerClasses: '',
        errorClasses: 'row color_red',
        errorHeadlineSize: 4,
      }}
      config={{
        useCookies: true,
        autoLogin: true,
        secondLastName: false,
        recaptcha: {
          enabled: true,
          token: "your_site_key_here",
          position: "above",
          size: "invisible",
        },
        termsUrl: "http://my.site.com/terms",
        privacyUrl: "http://my.site.com/privacy",
        GDPRUrl: "http://my.site.com/gdpr",
        signOutUrl: '/sign-out',
        signOutPageHomeUrl: '/homepage',
        signOutPageSignInUrl: '/sign-in',
        signOutPageSignUpUrl: '/register',
        profileUrl: '/profile',
        dobRegistration: true,
        dobRequiredRegistration: true,
        googleButtonWidth: 400,
        googleButtonHeight: 30,
        registrationAge: 14,
      }}
    />);
  }
}

export default Identity;

SPA Localization

All text within the SPA can be localized by passing a custom localization object with alternative/translated content. For a full list of all text that can be customized please see the localization section below.

SPA Styles

By default we provide bootstrap classes on all components for you. In order to match the look and feel of your project we expose certain classes within the SPA that you can set to your existing CSS classes. For a full list of all styles that can be customized please see the styles section below.

Identity Forms

  • Sign Up - Create a new account
  • Sign In - Login to your existing account
  • Profile - View/edit user profile
  • Manage - View order history and see/cancel current subscription
  • Email Verification - Allow users to verify their email address
  • Forgot Password - Request a link to change the user's password
  • Reset Password - Allow a verified user to set a new password
  • Order History - A table to display/sort orders
  • Change Password - A form for changing the user's profile after they've logged in
  • Magic Link - A form to get a one time login magic link code
  • Sign Out - A form to destroy the user's session and let them sign in again or create a new account

Sign Up Form

Allows a user to create a new account on your site

PropertyTypeDescription
useCookies (required)BooleanWhether or not to use cookies
doLogin (required)BooleanIf true, signs the user in after a successful sign up
successUrl (required)StringWhere the user should be redirected to after a successful sign up
headerPropsObjectProps to pass to the Header form element at the top of the profile form
saveChangesPropsObjectProps to pass to the SaveChanges form submit button
firstNamePropsObjectProps to pass to the FirstNameInput form element
lastNamePropsObjectProps to pass to the LastNameInput form element
signInButtonPropsObjectProps to pass to the SignInButton form element
errorTextObjectLocalization of all SDK API error messages
<SignUpForm
  useCookies={false}
  doLogin={true}
  successUrl="http://my.site.com/profile"
/>

Sign In Form

Allows a user with an existing account to login to that account

PropertyTypeDescription
loginSuccessUrl (required)StringURL to redirect the user to upon successful login, defaults to /profile )
cookieBooleanUse cookies to store user authentication
recaptchaTokenStringThe ReCaptcha token
wrapperClassesStringClasses to apply around the sign in form
errorClassesStringClasses to apply to sign in form error messages
headerPropsObjectProps to pass to the Header form element at the top of the sign up form
emailInputPropsObjectProps to pass to the EmailInput form element
passwordInputPropsObjectProps to pass to the PasswordInput form element
forgottenPasswordLinkPropsObjectProps to pass to the ForgotPasswordLink form element
signInButtonPropsObjectProps to pass to the SignInButton form element
rememberMeCheckboxPropsObjectProps to pass to the RememberMeCheckbox form element
errorTextObjectLocalization of all text and error codes
<SignInForm
  loginSuccessUrl="http://my.site.com/profile"
/>

Profile Form

Allows a user to view and edit their profile information

PropertyTypeDescription
wrapperClassesStringthe classes to use on around form elements
headerPropsObjectproperties to pass to the Header form element
firstNamePropsObjectproperties to customize the FirstNameInput element
lastNamePropsObjectproperties to customize the LastNameInput element
secondLastNamePropsObjectproperties to customize the SecondLastNameInput element
displayNamePropsObjectproperties to customize the DisplayName element
emailInputPropsObjectproperties to customize the EmailInput element
DOBInputPropsObjectproperties to customize the DOBInput element
genderRadioButtonsPropsObjectproperties to customize the GenderRadioButtons element
addressContainerPropsObjectproperties to customize the AddressContainer element
validateFullAddressCallbackFunctioncustom function that validates the address
saveChangesButtonPropsObjectproperties to customize the SaveChangesButton element
errorClassesStringthe classes applied to the error messages displayed in case of failure
successClassesStringthe classes applied to the success messages displayed in case of success
errorTextObjectLocalization of all SDK API error messages
successTextObjectLocalization of all SDK API success messages
getProfileFailureUrlStringthe url to redirect the user in case of failure to retrieve the user profile
requireEmailVerificationBooleanthe condition of requiring the user to verify their email address before accessing their profile information (defaults to false)
verifyEmailUrlStringthe url to redirect the user in the case that the email is not verified
<ProfilePageForm
  headerProps={{
    title: "Profile Page",
  }}
  DOBInputProps={{
    dateFormat: "US",
  }}
  getProfileFailureUrl="http://my.site.com/login"
  verifyEmailUrl="http://my.site.com/verify-email"
/>

Manage Form

Allows a user to view and/or cancel their subscription and see their latest order history

PropertyTypeDescription
localization (required)ObjectObject containing all localization values passed from the SPA
stylesObjectObject containing all style customization prop values
<ManageSubsPage
  localization={localizationObject}
  styles={stylesObject}
/>

Email Verification Form

Allows a user to verify they are using a valid email address.

PropertyTypeDescription
successUrlStringRedirect to this URL on successful verification
successTextStringMessage to display on successful verification
nonceStringA nonce to verify the email through the user's email provider
<EmailVerification
  successUrl="/#profile"
/>
How To Verify An Email Address

When you set the verify email address flag to true in the Subs admin the IdentitySPA and the Login Form will require a verified email addresses before the user can login and view their profile or manage their subscription. Upon account creation an email must be set to the user's unverified email address and include a link back to the following URL pattern in order to complete the full verification process: https://my.site.com/{subscriptions-url}?nonce={nonce}/#verify

Forgot Password Form

Allows a user to request a link to reset their password

PropertyTypeDescription
headerStringthe forgot password header text
instructionsStringinstructions on how to fill out the form to get a reset password link
emailInputPropsObjectproperties to pass to the EmailInput form element
resetLinkButtonPropsObjectproperties to pass to the ResetLinkButton form element
magicLinkButtonPropsObjectproperties to pass to the MagicLinkButton form element
wrapperClassesStringclasses wrapper around form
instructionClassesStringclasses that wrap around the instructions for this form
errorClassesStringclasses for error messages
successClassesStringclasses for success messages
defaultResponseTextObjectan object with all default text, error codes and response messages to override the default values
<ForgotPasswordForm
  header="Forgot Your Password?"
  instructions="Enter your email address and click the button to send a reset password link to your email"
/>

Reset Password Form

Allows a user to reset their password. Requires an email be sent to the user with a nonce in the format of https://my.site.com/{subscriptions-url}?nonce={nonce}/#reset-password

React PropTypeDescription
successUrl (required)StringWhere the user is redirected after they successfully change their password
nonceStringoptional nonce to use in place of the nonce coming from the window URL hash
headerStringthe forgot password header text
loadingStringmessage to display while the component is loading
wrapperClassesStringclasses wrapper around form
loadingClassesStringproperties to pass to the EmailInput form element
headerClassesStringclasses to pass to the header
passwordPropsObjectproperties to pass to the first password input
confirmPasswordPropsObjectproperties to pass to the second confirm password input
resetButtonPropsObjectproperties to pass to the reset password button at the bottom of the form
instructionClassesStringclasses that wrap around the instructions for this form
errorClassesStringclasses for error messages
successClassesStringclasses for success messages
defaultTextObjectan object with all default text, error codes and response messages to override the default values
<ResetPasswordForm
  successUrl="http://my.site.com/login"
/>

Manage Subscriptions Status Bar

PropertyTypeDescription
statusLabelString, JSX ElementStatus Label
statusInputPlaceholderStringStatus Input Placeholder
statusRenderInputContentFunctionStatus Render Input Content
actionLabelString, JSX ElementAction Label
actionInputPlaceholderStringAction Input Placeholder
actionCancelReasonsArrayAction Cancel Reason Options List
actionBarCancelSubscriptionButtonContentString, JSX ElementAction Bar Cancel Subscription Button Content
actionBarSubmitButtonContentString, JSX ElementAction Bar Submit Button Content
actionBarCancelButtonContentString, JSX ElementAction Bar Cancel Button Content
actionBarRenewSubscriptionButtonContentString, JSX ElementAction Bar Renew Subscription Button Content
actionBarRenewSubscriptionRenderLabelContentFunctionAction Bar Renew Subscription Render Label Content
actionBarShowSubscriptionsButtonContentString, JSX ElementAction Bar Show Subscriptions Button Content
actionBarShowSubscriptionsLabelContentString, JSX ElementAction Bar Show Subscriptions Label Content
actionAlertSuccessContentString, JSX ElementAction Alert Success Content
actionAlertErrorContentString, JSX ElementAction Alert Error Content
actionAlertDurationNumberAction Alert Duration
loadingIndicatorString, JSX ElementLoading Indicator
renewSubscriptionCampaignIDString, Number"Renew Subscription" CampaignID
showSubscriptionsCampaignIDString, Number"Show Subscription" CampaignID
renewSubscriptionURLStringRenew Subscription URL
showSubscriptionOptionsURLStringShow Subscription Options URL
stylesObjectObject containing all custom class and styling props
<ManageSubStatusBar
  statusLabel="Current Subscription"
  statusInputPlaceholder=""
  statusRenderInputContent={subObj => `${subObj.productName} - ${subObj.subscriptionID}`}
  actionLabel="Reason for Cancellation"
  actionInputPlaceholder="Select reason..."
  actionCancelReasons={[
    "Price is too expensive"
    "Didn't utilize my subscription enough"
    "Found a service I like better"
    "I just don't want it anymore"
  ]}
  actionBarCancelSubscriptionButtonContent="Cancel Subscription"
  actionBarSubmitButtonContent="Submit & Cancel"
  actionBarCancelButtonContent="Nevermind"
  actionBarRenewSubscriptionButtonContent="Renew subscription"
  actionBarRenewSubscriptionRenderLabelContent={(subObj) => {
    return (<><i className="mr-2">{subObj.productName}</i>subscription has expired</>);
  }}
  actionBarShowSubscriptionsButtonContent="Show subscription options"
  actionBarShowSubscriptionsLabelContent={(<i className="mr-2">No current subscriptions</i>)}
  actionAlertSuccessContent="Subscription Cancellation Successful!"
  actionAlertErrorContent="Subscription Cancellation Failed"
  actionAlertDuration={4000}
  loadingIndicator={(<div className="alert alert-warning">Loading data...</div>)}
  renewSubscriptionCampaignID={12345}
  showSubscriptionsCampaignID={67890}
  renewSubscriptionURL="/packages-feature-subscriptions-src-children-retail-spa-spa#/campaign"
  showSubscriptionOptionsURL="/packages-feature-subscriptions-src-children-retail-spa-spa#/campaign"
  styles={stylesObject}
/>

Order History Table

Creates a responsive, sortable table of the user's order history with expandable rows for overflowing fields (dynamic/responsive)

PropertyTypeDescription
titleStringTitle to use on the table
displayConfigFunctionFunction that returns a configuration object used for providing table display parameters to child Table component
stylesObjectObject containing all custom class and styling props
<OrderHistoryTable
  title="Table Title"
  styles={stylesObject}
  displayConfig={displayType => ({
    mobile: {
      numColumns: 2,
      displayClasses: `d-${displayType} d-sm-${displayType}`,
      hiddenClasses: "d-none d-sm-none",
    },
    tablet: {
      numColumns: 3,
      displayClasses: `d-md-${displayType}`,
      hiddenClasses: "d-md-none",
    },
    desktop: {
      numColumns: 5,
      displayClasses: `d-lg-${displayType} d-xl-${displayType}`,
      hiddenClasses: "d-lg-none .d-xl-none",
    },
  })}
/>

Change Password Form

This allows a user to change their password to their account. They must already be signed into their account in order to use this form.

PropertyTypeDescription
headerStringTitle shown above the form
headerClassesStringClasses to apply to the header text
loadingStringText to display for the loading message
loadingClassesStringClasses to apply to the loading text
wrapperClassesStringClasses to apply to the div around the form
errorClassesStringClasses to apply to the error messages return from the form
successClassesStringClasses to apply to the success messages return from the form
oldPasswordPropsObjectValues passed to the passwordInput component used for the old password input field
newPasswordPropsObjectValues passed to the passwordInput component used for the new password input field
confirmPasswordPropsObjectValues passed to the passwordInput component used for the confirm password input field
saveChangesButtonPropsObjectValues passed to the button component used to save changes
defaultTextObjectLocalzation of text and error codes
<ChangePassword
  loading="Loading, please wait..."
  successClasses: "text-success mb-2",
  newPasswordProps: {{
    label: "Enter Your New Password",
  }}
/>

This allows a user to request a one time access code to login to their account if they've forgotten their password. It requires a nonce be sent to them with a link to their email address in the format of https://my.site.com/{subscriptions-url}?nonce={nonce}/#magic-link

React PropTypeDescription
wrapperClassStringClasses applied to the wrapper div
successUrlStringThe url to redirect to when a successful nonce is verified
successTextStringThe text to show when a nonce is successfully verified
nonceStringThe nonce to verify (will check from the URL by default but can also be passed as a prop)

<MagicLinkForm />

Sign Out Form

When a user is logged in and this form is rendered this form will automatically clear their session and display options to allow them to log back in, create a new account, or go back to the homepage.

React PropTypeDescription
pageTextStringText to show above the links on the page
wrapperClassesStringClasses to apply to the wrapper div
textClassesStringClasses to apply to the text at the top of the sign out form
homeTextStringThe text for the home url link
homeUrlStringThe url for redirecting the user back to the homepage
redirectLinkHomeClassesStringClasses to apply to the homepage redirect link
signInTextStringThe text for the sign in url link
signInUrlStringThe url for redirecting the user to the sign in page
redirectLinkSignInClassesStringClasses to apply to the sign in url
signUpTextStringThe text for the sign up url link
signUpUrlStringThe url for redirecting the user to the sign up page
redirectLinkSignUpClassesStringClasses to apply to the sign up url
<SignOutForm
  pageText="You have successfully logged out!"
/>

Google Sign On

Creates an out-of-the-box Sign On with Google feature.

Required Setup
  • The correct google ID must be setup in the Subs Admin for the particular tenant (apiOrigin).
  • The component must be placed on a valid https page. (For local development ngrok was used).
React PropTypeDescription
configObjectthe object containing all the configurations for the GoogleSignOn feature.
stylesObjectthe object containing all the styling classes for the GoogleSignOn feature.
textObjectthe object containing all the error messages for the Google Sign On Feature
redirectLinkStringthe url to which the user gets redirected after a successful Google sign on.
googleButtonWidthNumberwidth in pixels accepted by the Google Sdk (Defaults to 120).
googleButtonHeightNumberheight in pixels accepted by the Google Sdk (Defaults to 36).
googleButtonLongTitleBooleanboolean value that sets whether to display long labels such as "Sign in with Google" rather than "Sign in" (Defaults to false).
googleButtonThemeStringThe color theme of the button: either light or dark (defaults to "light").
wrapperClassesStringclasses to style the button wrapper
sdkErrorClassesStringclasses to style the error message in case the google sdk fails to load.
signOnErrorClassesStringclasses to style the error message in case the google Sign in fails.
successCallbackFunctionfunction that is invoked after a succesful sign on
failureCallbackFunctionfunction that is invoked after a failed sign on
attemptCallbackFunctionfunction that is invoked after the button click
sdkErrorMessageStringerror message to be displayed in case the Google sdk fails to load
signOnErrorMessageStringerror message to be displayed in case the Google sign on fails for any reason
Additional Customizations

More Google button customization options are available on https://developers.google.com/identity/sign-in/web/reference#ui_elements

  <GoogleSignOn
  config= {{
    redirectLink: "/profile",
    googleButtonWidth: 400,
    googleButtonHeight: 40,
    googleButtonLongTitle: true,
    googleButtonTheme: "dark",
  }}
  styles={{
    wrapperClasses: "d-flex flex-column align-items-center justify-content-center mt-3",
    sdkErrorClasses: "text-danger",
    signOnErrorClasses: "text-danger",
  }}
  />

Facebook Sign On

Creates an out-of-the-box Sign On with Facebook feature.

Required Setup
  • The correct facebook APP ID and App Secret must be setup in the Subs Admin for the particular tenant (apiOrigin).
  • The component must be placed on a valid https page. (For local development ngrok was used).
React PropTypeDescription
configObjectthe object containing all the configurations for the FacebookSignOn feature.
stylesObjectthe object containing all the styling classes for the FacebookSignOn feature.
textObjectthe object containing all the error messages for the FacebookSignOn Feature
redirectStringthe url to which the user gets redirected after a successful facebook sign on.
fbButtonSizeStringthe size of the button configured by the facebook sdk, can be "large", "medium" or "small". Defaults to "large".
fbButtonTypeStringthe button text accepted by the facebook sdk, must be either "login_with" or "continue_with". Defaults to "login_with".
fbIncludePictureBooleana boolean value accepted by the facebook sdk that allows the component to either include the name and profile picture when the user is signed into Facebook or not.
wrapperClassesStringclasses to style the button wrapper
sdkErrorClassesStringclasses to style the error message in case the Facebook sdk fails to load.
signOnErrorClassesStringclasses to style the error message in case the Facebook Sign On fails.
successCallbackFunctionfunction that is invoked after a succesful sign on
failureCallbackFunctionfunction that is invoked after a failed sign on
attemptCallbackFunctionfunction that is invoked after the button click
sdkErrorMessageStringerror message to be displayed in case the Facebook sdk fails to load
signOnErrorMessageStringerror message to be displayed in case the Facebook Sign On fails for any reason
  <FacebookSignOn
  config={{
    fbButtonSize: "medium",
    fbButtonType: "continue_with",
    }}
  styles={{
    wrapperClasses: "border border-success d-flex justify-content-center"
  }}
  />

Retail & Sales

This allows you to use pre-built solutions for managing campaigns, displaying products, adding/removing items to your cart, payment processing and confirmation of your purchases.

SPA Configuration

This is a Single Page App that has all of the pre-configured workflow already setup and ready for you to customize and start using.

PropertyTypeDescription
useCookies (required)BooleanWhether or not to use cookies
autoLoginBooleanAutomatically login via a cookie or local storage
checkoutUrlStringHash fragment used when user selects an offer
loginUrlStringHash fragment used when user needs to login
addItemToCartFailureUrlStringHash fragment used when we encounter an error adding an item to the cart
confirmationPageRedirectLinkURLStringHash fragment used when user clicks the "Start Reading" button on the confirmation page
errorUrlStringHash fragment used when an error is encountered
confirmUrlStringHash fragment used when user has paid
offersUrlStringHash fragment used when the user is looking at offers
recaptcha (required)ObjectConfig for recaptcha
registerUrlStringHash fragment used when user wants to create a new account

Hash Routes

These are the hash routes used in the retail SPA:

#/ and #/campaign – This pulls up the campaign to display the products and subscriptions available for purchase. This uses data from a content source.

#/checkout – This displays the items currently in the user’s shopping cart.

#/confirmation – This displays a confirmation message after the payment has been successfully processed by the payment processor.

#/error – This is the default error message if something has gone wrong at any point during this process.

SPA Sample Usage

This will create the retail spa with debugging messages.

import Subscriptions from '@arc-core-components/feature_subscriptions';

<Subscriptions.RetailSPA
  debug={true}
  styles={this.props.styles}
  config={this.props.configuration}
  localization={this.props.translatedMessages}
  offersData={this.props.offers}
/>

SPA Localization

All text within the SPA can be localized by passing a custom localization object with alternative/translated content. For a full list of all text that can be customized please see the localization section below.

SPA Styles

By default we provide bootstrap classes on all components for you. In order to match the look and feel of your project we expose certain classes within the SPA that you can set to your existing CSS classes. For a full list of all styles that can be customized please see the styles section below.

Retail Forms

  • Campaign - displays a list of the current products in a campaign
  • Cart - displays a list of items in the user's shopping cart along with

Campaign Form

Allows a user to view the information related to a campaign in form of a headline image, headline text and one or several products. If a product contains several rates, the user has the option to select one, the product then being added to the user cart.

PropertyTypeDescription
offersObject (required)ObjectThe object that contains all the offer related information that has been set up in the Subscriptions Admin
productCardsContainerPropsObjectProperties (text and styles) applied to the productCardsContainer element
headlineImagePropsObjectProperties (text and styles) applied to the HeadlineImage element
disclaimerMessagePropsObjectProperties (text and styles) applied to the Header (Disclaimer Message) component
checkoutUrlStringThe url of the checkout page where the user is able to interact with the current contents of their cart
loginUrlStringThe url of the login page where the user can either login or register and then proceed to checkout without losing the contents of their cart
addItemToCartFailureUrlStringThe url of the page on which the user lands in case the add to cart process fails
  <Subscriptions.Campaign
    checkoutUrl= "/checkout"
    loginUrl= "/login"
    addItemToCartFailureUrl= "/404"
    headlineImageProps={{
      wrapperClasses: String
      wrapperStyles: Object,
      smBrkPnt: String,
      mdBrkPnt: String,
      pageTitleSize: Number,
      titleClasses: String,
      pageSubTitleSize: Number,
      subTitleClasses: String,
    }}
    productCardsContainerProps= {{
      cardsWrapper: String,
      productCardsProps: {
        wrapperClasses: String,
        headerProps: {
          className: String,
        },
        unorderedListProps: {
          wrapperClasses: String,
          itemClasses: String,
        },
        getOfferButtonProps: {
          className: String,
        },
        lazyLoadingImageProps: {
          wrapperClasses: String,
          imageSrc: String,
          imageAlt: String,
          imageClasses: String,
          loaderSrc: String,
          loaderAlt: String,
          loaderClasses: String,
        },
        productPriceRadioButtonsProps: {
          wrapperClasses: String,
          label: String,
          labelClasses: String,
          radioContainerClasses: String,
        },
        singleProductPriceFieldProps: {
        size: Number,
        className: String,
        },
      },
    }}
    disclaimerMessageProps= {{
      size: Number,
      children: String,
      className: String,
    }}
    offersObject= {OFFERS_OBJECT}
  />

Notes on the OFFERS_OBJECT

In the current implementation with Fusion, the offers object is returned by making an api call that uses the campaign-name as a URI parameter, which is editable via a custom field.

A resolver needs to be setup in the sources folder, that would handle the API assembly logic.

const resolve = (params) => {
  const website = params['my-site'];
  const { 'campaign-name' } = params;
  return `https://api-${org}-${website}.cdn.arcpublishing.com/retail/public/v1/offer/live/${campaign-name}`;
};

export default {
  resolve,
  params,
};

The resolver can then be called inside the feature, passing the returned offers object to the Campaign component as a property.

    ...
    const { cached, fetched } = this.getContent('offers', { campaignName: props.customFields.defaultCampaign });
    this.state = { offers: cached };
    fetched.then((offers) => {
      this.setState({ offers });
    });
    ...
    ...
    ...
    render(){
      return(
        <Subscriptions.Campaign
          ...
          ...
          offersObject= {this.state.offers}
        />
      )
    }
    ...

Cart Form

This will quickly create a cart that displays a user's items they are trying to purchase, allows them to remove items, and provides a summary for the cost of those items.

PropertyTypeDescription
config (required)ObjectAn object containing the cart's configuration
localizationObjectAn object that includes the default text and error messages for the cart
stylesObjectAn object with style classes
import Subscriptions from '@arc-core-components/feature_subscriptions';

<Subscriptions.Cart />

Paywall

The paywall is comprised of two parts:

  • A portal component that loads the paywall script (p.js) and runs it to check the user's registration status.

  • A modal with contents, buttons, links etc wrapped by the portal.

If you want the prebuilt modal contents you can pass a PaywallModal component into the PaywallPortal. Otherwise pass in your own children if you need something more flexible. It's pretty barebones so this will most likely happen.

Paywall Domains

  • apiOrigin and paywallScriptSrc should look like the following:
  • If you add https:// to the paywallApiOrigin ArcP which is the paywall script adds https twice, it will break.

  • The domain of paywallScriptSrc and paywallApiOrigin have to be the same, if they're not you get a CORS error and you'll get an error that the entitlement check failed (this is an under the hood request ArcP makes to the sales api to determine user registration).

  • You will need versions of these url's for both sandbox and production. It's best to keep them in site properties for each of your sites.

Paywall p.js Script (ArcP)

  • This will be located at https://my.site.cdn.arcpublishing.com/arc/subs/p.js

  • If it's not available you will need to have it provisioned by the Arc Delivery team (DEL - minimum 1 week lead time).

  • The p.js script is generated when you activate a paywall in the subs admin. Only one paywall can be active at a time. When you activate a new paywall you will get a new p.js. If you don't and the rules aren't updating when you run ArcP on the frontend, contact arc subscriptions support.

  • You can type ArcP into the browser console to make sure the p.js script loaded (loaded by PaywallPortal via the paywallScriptSrc) properly.

  • You can furthermore type ArcP._facts or ArcP._rules to see what facts were collected about the user and which paywall ruleset is being loaded from the admin. The _facts and _rules are compared by p.js to determine if the paywall should be triggered or not. If the paywall is triggered the modal will appear, and then the callback you entered thru the paywallFunction prop will also fire. You can also pass in the resultsCallback prop if you want anything else to happen after ArcP runs regardless whether the paywall is triggered or not as a follow up.

Setting Up A The Paywall In Fusion

Create a wrapper component and collect the necessary props the paywall needs for ArcP to run including:

  • paywallScriptSrc - the source of your p.js file

  • contentType - from globalContents - from the type field

  • contentSection - from globalContents - see below, it should come from the websites field

  • contentId - from globalContents - either the source id or the canonical_url

  • Without the above props ArcP cannot function

PaywallPortal Props

React PropTypeDescription
paywallScriptId (required)StringA unique id for the p.js script tag.
paywallScriptSrc (required)StringA src url to get p.js from the cdn.
contentType (required)Stringfrom globalContents - from the type field.
contentSection (required)Stringfrom globalContents - see below, it should come from the websites field.
contentId (required)Stringfrom globalContents - either the source id or the canonical_url.
paywallFunctionFunctionWhatever you want to happen when ArcP triggers the paywall. The modal always pops up regardless of what function you pass in here.
customSubCheckFunctionPassed to ArcP if you want to override the default subscription status check.
customRegCheckFunctionPassed to ArcP if you want to override the default logged in status check.
resultsCallbackFunctionWhatever you want to happen after ArcP.run returns.
childrenElementsYou can pass in your own child elements instead of the contents of PaywallModal.

PaywallPortal Configuration

Example of how to setup the PaywallPortal with premade PayallModal contents and the IconButton (X button):

import Subscriptions from '@arc-core-components/feature_subscriptions';

  <Subscriptions.PaywallPortal
    overlayClassName="modal-dialog"
    contentClassName="modal-content modal-body"
    paywallScriptId="pjs-script"
    paywallScriptSrc="https://my.site.cdn.arcpublishing.com/arc/subs/p.js"
    contentType="your-content-type"
    contentSection="your-content-section"
    contentId="your-story-content-id"
    >
    <Subscriptions.IconButton
      iconClassName="close"
      onClickHandler={
        () => (
          window.location.href = 'your-close-modal-redirect-location'
        )
      }
      keyString="Escape"
      >
        <span>&times;</span>
    </Subscriptions.IconButton>
    <Subscriptions.PaywallModal
      styles={
        {
          paywallModalHeaderClassName: "",
          paywallModalHeaderSize: 2,
          paywallModalSubheaderClassName: "",
          paywallModalDescriptionClassName: "",
          paywallModalOfferClassName: "",
          paywallModalAllOffersClassName: "",
          paywallModalSignInClassName: "",
          paywallModalSignInMessageClassName: "",
        }
      }
      text={
        {
          paywallModalHeaderText: "Welcome to the PayWall",
          paywallModalSubheaderText: "You are out of free stories.",
          paywallModalDescriptionText: "Subscribe for $25 per month.",
          paywallModalOfferText: "Subscribe",
          paywallModalAllOffersText: "See all offers",
          paywallModalSignInText: "Sign In.",
          paywallModalSignInMessageText: "Already have an account? ",
        }
      }
      links={
        {
          paywallModalOfferUrl: "your-retail-SPA-url/#campaign?code=your-campaign-code",
          paywallModalAllOffersUrl: "your-default-offer-retail-SPA-url/#campaign",
          paywallModalSignInUrl: "your-identity-SPA-url/#sign-in",
        }
      }
      >
    </Subscriptions.PaywallModal>
  </Subscriptions.PaywallPortal>

Example Paywall Component

This is an example of an implementation of a paywall component in a fusion feature pack repository. It should be added to all article templates and pages that should trigger a paywall.

import React, { PureComponent } from 'react';
import Subscriptions from '@arc-core-components/feature_subscriptions';
import PropTypes from 'fusion:prop-types';
import Consumer from 'fusion:consumer';

/**
* We don't ever want to render the paywall server side
* so we can use this function to make sure we exit the
* render loop if this is a server side render
**/
function isServerSide() {
  return typeof window === 'undefined';
}

@Consumer
class Paywall extends PureComponent {

  /**
  * Handle the redirect back to a page that doesn't need
  * a subscription when they close the paywall modal
  **/
  handleRedirect = () => {
    const {
      customFields: {
        paywallIconButtonUrl,
      },
    } = this.props;
    window.location.href = paywallIconButtonUrl;
  };

  /**
  * This is the logic (or something similar) you'll need to implement
  * in order to remove or hide the article body from the DOM when the
  * paywall is triggered
  **/
  hideArticleBody = () => {
    alert('TODO: update hide article body logic');

    /* if (document.querySelector('your_article_body_parent_class') && document.querySelector('your_article_body_class')
    && !this.props.isAdmin) {
      const article = document.querySelector('your_article_body_parent_class');
      const body = document.querySelector('your_article_body_class');
      article.removeChild(body);
    } */
  }

  /**
  * Our recommendation is that you display the modal inline when you are in PB admin
  * to prevent it from covering content on your page. This applies to the modal overlay.
  **/
  getModalOverlayClasses = (isAdmin) => {
    return isAdmin ? 'background_gray flex align_items_center justify_center'
      : 'fullscreen fixed background_gray flex align_items_center justify_center z_index_highest';
  }

  /**
  * Our recommendation is that you display the modal inline when you are in PB admin
  * to prevent it from covering content on your page. This applies to the content in the modal.
  **/
  getModalContentClasses = (isAdmin) => {
    return isAdmin ? 'flex container_column justify_space_between background_white paywall paywall-modal_container'
      : 'flex container_column justify_space_between background_white paywall paywall-modal_container relative';
  }

  /**
   * Render the paywall component
   */
  render() {
    const { arcSite, isAdmin } = this.props;
    const { paywallScriptSrc } = getProperties()[arcSite]; // or wherever this is defined in your site properties JSON files
    const {
      _id: contentId,
      type: contentType,
    } = this.props.globalContent;
    const {
      websites: {
        [arcSite]: {
          website_section: {
            _id: sectionId,
          },
        },
      },
    } = this.props.globalContent;
    const modalOverlayClasses = this.getModalOverlayClasses(isAdmin);
    const modalContentClasses = this.getModalContentClasses(isAdmin);
    const iconClassName = 'modal_icon pointer absolute';
    const iconKeyString = 'Escape';
    const paywallScriptId = 'pjsscript';
    const paywallModalHeaderClassName = 'paywall-modal_header';
    const paywallModalSubheaderClassName = 'paywall-modal_sub-header';
    const paywallModalDescriptionClassName = '';
    const paywallModalOfferClassName = 'button button_primary';
    const paywallModalAllOffersClassName = '';
    const paywallModalSignInMessageClassName = '';
    const paywallModalSignInClassName = '';
    const paywallModalSignUpMessageClassName = '';
    const paywallModalSignUpClassName = '';
    const {
      customFields: {
        paywallModalHeaderText,
        paywallModalSubheaderText,
        paywallModalDescriptionText,
        paywallModalOfferText,
        paywallModalAllOffersText,
        paywallModalSignInText,
        paywallModalSignInMessageText,
        paywallModalOfferUrl,
        paywallModalAllOffersUrl,
        paywallModalSignInUrl,
        paywallModalSignUpMessageText,
        paywallModalSignUpUrl,
        paywallModalSignUpText,
      },
    } = this.props;

    return !paywallScriptSrc || isServerSide() ? null : (
      <Subscriptions.PaywallPortal
        overlayClassName={modalOverlayClasses}
        contentClassName={modalContentClasses}
        paywallScriptId={paywallScriptId}
        paywallScriptSrc={paywallScriptSrc}
        contentId={contentId}
        contentType={contentType}
        contentSection={sectionId}
        paywallFunction={this.hideArticleBody}
      >
        <Subscriptions.IconButton
          iconClassName={iconClassName}
          onClickHandler={this.handleRedirect}
          keyString={iconKeyString}
        >
          <span>&times;</span>
        </Subscriptions.IconButton>
         <p
          className={paywallModalHeaderClassName}
        >
          {paywallModalHeaderText}
        </p>
        <p
          className={paywallModalSubheaderClassName}
        >
          {paywallModalSubheaderText}
        </p>
        <p
          className={paywallModalDescriptionClassName}
        >
          {paywallModalDescriptionText}
        </p>
        <a
          href={paywallModalOfferUrl}
          className={paywallModalOfferClassName}
        >
          {paywallModalOfferText}
        </a>
        <p className="text text_align_center">
          <a
            href={paywallModalAllOffersUrl}
            className={paywallModalAllOffersClassName}
          >
            {paywallModalAllOffersText}
          </a>
        </p>
        <div className="text text_align_center margin_center">
          <p
            className={paywallModalSignInMessageClassName}
          >
            {paywallModalSignInMessageText}
            &nbsp;
            <a
              href={paywallModalSignInUrl}
              className={paywallModalSignInClassName}
            >
              {paywallModalSignInText}
            </a>
          </p>
          <p
            className={paywallModalSignUpMessageClassName}
          >
            {paywallModalSignUpMessageText}
            &nbsp;
            <a
              href={paywallModalSignUpUrl}
              className={paywallModalSignUpClassName}
            >
              {paywallModalSignUpText}
            </a>
          </p>
        </div>
      </Subscriptions.PaywallPortal>
    );
  }
}

Paywall.propTypes = {
  arcSite: PropTypes.string,
  isAdmin: PropTypes.boolean,
  globalContent: PropTypes.object,
  customFields: PropTypes.shape({
    paywallModalHeaderText: PropTypes.string.tag({
      defaultValue: 'Subscribe to Keep Reading.',
      name: 'Header',
    }),
    paywallModalSubheaderText: PropTypes.string.tag({
      defaultValue: 'You do not have any free stories left this month.',
      name: 'Subheader',
    }),
    paywallModalDescriptionText: PropTypes.string.tag({
      defaultValue: 'Enjoy unlimited access with your subscription.',
      name: 'Offer Description',
    }),
    paywallModalOfferText: PropTypes.string.tag({
      defaultValue: 'Upgrade',
      name: 'Link to Offer Text',
    }),
    paywallModalAllOffersText: PropTypes.string.tag({
      defaultValue: 'See all subscription options.',
      name: 'Link to All Offers Text',
    }),
    paywallModalSignInText: PropTypes.string.tag({
      defaultValue: 'Sign In.',
      name: 'Link to Sign In Text',
    }),
    paywallModalSignInMessageText: PropTypes.string.tag({
      defaultValue: 'I have an account. ',
      name: 'I Have An Account Text',
    }),
    paywallModalOfferUrl: PropTypes.string.tag({
      defaultValue: '/',
      name: 'URL To Offer Page',
    }),
    paywallModalAllOffersUrl: PropTypes.string.tag({
      defaultValue: '/',
      name: 'URL To ALL Offers Page',
    }),
    paywallModalSignInUrl: PropTypes.string.tag({
      defaultValue: '/',
      name: 'URL To Sign In Page',
    }),
    paywallIconButtonUrl: PropTypes.string.tag({
      defaultValue: '/',
      name: 'Close Button Redirect URL',
    }),
    paywallModalSignUpMessageText: PropTypes.string.tag({
      defaultValue: 'Your first time here? ',
      name: 'Sign Up Text',
    }),
    paywallModalSignUpText: PropTypes.string.tag({
      defaultValue: 'Create an Account.',
      name: 'Sign Up Link Text',
    }),
    paywallModalSignUpUrl: PropTypes.string.tag({
      defaultValue: '/subscription#register',
      name: 'Sign Up URL',
    }),
  }),
};

export default Paywall;

Form Elements

ElementDescription
addressContainerContains all the fields needed to collect address information from a users
alreadyASubscriberLink for users to click on if they are already a subscriber
buttonA baseline (empty) button that can be extended or customized
buttonOptionsA group of up to 3 buttons that display different options
cartEmptyA component to display an empty cart
cartItemDisplays a single item in a cart
cartSummaryDisplays a summary of the items in the cart
checkboxA single form input of type checkbox
checkoutButtonA button for checking out your cart
cityInputAn address field for the city a user lives in
confirmPasswordInputA password input field for confirming your password
countryDropdownA dropdown address box for selecting the country a user lives in
displayNameInputAn input field for entering a user's display name
DOBInputA input field for entering a user's date of birth (accepts US or EU date formats)
dropdownA baseline (empty) dropdown that can be extended or customized
emailInputAn input field for entering the user's an email address
firstAddressInputAn address input field for entering the first line of a user's address
firstNameInputAn input field for entering the user's first name
forgotPasswordLinkA link to direct users to the lost password form
GenderRadioButtonsRadio buttons for a user to select their gender preference
getOfferButtonA button to accept a campaign offer/product
headerCreates a custom h# header
headlineImageA responsive image that is intended for use on the top of the campaign page or for a large image
iconButtonA button with an SVG icon in it
inputA baseline (empty) input field that can be extended or customized
keepReadingButtonA button to keep reading from where the user left off
lastNameInputAn input for entering a user's last name
lazyLoadingImageLoads an image using a lazy loader
manageSubscriptionsButtonA button you can click to manage your subscription
manageSubStatusBarA status bar for managing subscriptions
modalA modal popup window
notLoggedInA message to show when the user is not logged in
passwordInputAn input field that accepts a user's password
phoneNumberInputAn input field that accepts a user's phone number
postalCodeInputAn address form field for entering a user's postal code
productCardA card for displaying information about a subscription or product
productCardsContainerA container that wraps all the product cards
productPriceRadioButtonsRadio button options specifically for listing prices of a subscription or product
radioButtonA baseline radio button input field that can be customized or extended
redirectLinkA link that when clicked redirects the user to a different url
rememberMeCheckboxA checkbox for a user to click to keep a cookie/localstorage of their login credentials
removeButtonA button to remove an item from a user's cart
resetPasswordButtonA button to reset a user's password
returnToCampaignLinkA link to return to a specific campaign/offers/products listing
saveChangesButtonPropsA button for a user to save their form changes
secondAddressInputAn address input field for entering the second line of a user's address
secondLastNameInputAn input field for entering a second last name
signInButtonA button to sign into a login form
signOutButtonA button to sign out
signUpButtonA button to sign up
singleProductPriceFieldA price field for products that don't have multiple price options
stateInputAn address field that gives user's the option of selecting a state or region
statusBarA base element for a 3 tab status bar that can be customized and extended
subscribeButtonA button that takes users to a campaign page
tableA baseline table component that can be customized and extended
termsAndConditionsAsks the user to agree to terms and conditions and privacy policy and GDPR requirements
unorderedListA baseline element for creating unordered lists, customizable and extendable

Functions & Analytics

This section contains information about built in analytics, input validation and utility functions.

Analytics

By default all analytics are stored in window.arcAnalyticsHistoryValue. You can alter where analytics are stored by setting window.arcAnalyticsHistoryKey = 'your_custom_analytics_key'; which would then allow you to access window.your_custom_analytics_key to retrieve all the analytics events. In addition you can listen for the events being broadcast to catpure them in real time or you can disable analytics completely by setting window.arcAnalyticsDisabled = true;

Events

These are stored in the ANALYTIC_EVENTS object containing all analytics events.

EventDescription
LOGINLogin form
LOGOUTLogout form
REGISTERRegistration form
CAMPAIGN_PAGECampaign/products form
ADD_ITEMWhen an item is added to the user's cart
REMOVE_ITEMWhen an item is removed from a user's cart
PAYMENT_PAGECart form
CONFIRMATION_PAGEConfirmation form
PAYWALL_HITActiviating the paywall form
VERIFIED_EMAILAttempting to verify an email
MAGIC_LINKAttempting to login with a magic link
CANCEL_SUBAttempting to cancel a subscription
PROFILE_PAGEWhen a user views the profile page

Actions

These are stored in the ANALYTIC_ACTIONS object containing all analytics actions.

ActionDescription
LOGIN_ATTEMPTAttempting to login
LOGIN_SUCCESSLogged in successfully
LOGIN_FAILEDLogin failure or invalid username/password
LOGOUT_SUCCESSLogged out successfully
LOGOUT_FAILEDLogged out failure
REGISTER_PAGE_VIEWViewing the register page
REGISTER_ATTEMPTAttempting to create an account
REGISTER_SUCCESSSuccessfully created an account
REGISTER_FAILEDFailed to create an account
CAMPAIGN_PAGE_VIEWViewed the campaign page
CAMPAIGN_PAGE_LEAVELeft the campaign page
CART_ADD_ITEM_SUCCESSSuccessfully added an item to their cart
CART_ADD_ITEM_FAILEDFailed to add an item to their cart
CART_REMOVE_ITEM_SUCCESSSuccessfully removed an item from their cart
PAYMENT_PAGE_VIEWSuccessfully viewed payment processor
PAYMENT_SUCCESSCompleted payment with the payment processor
PAYWALL_OPENWhen the paywall is open
VERIFIED_EMAIL_SUCCESSEmail was successfully verified
VERIFIED_EMAIL_FAILEDEmail verification failed
MAGIC_LINK_SUCCESSSucessfully logged in with a magic link
MAGIC_LINK_FAILEDFailed to login with a magic link
CANCEL_SUB_SUCCESSA subscription was successfully cancelled
CANCEL_SUB_FAILEDSubscription cancellation attempt failed
PROFILE_PAGE_VIEWUser's profile was viewed
PROFILE_UPDATE_SUCCESSUser's profile was successfully updated
PROFILE_UPDATE_FAILEDUser's profile update failed

sendAnalyticEvent(event:String, action:Object)

This creates an analytics event on button press.

import Subs from '@arc-core-components/feature_subscriptions';

render () {
  const { LOGIN } = Subs.ANALYTIC_EVENTS;
  const { LOGIN_ATTEMPT } = Subs.ANALYTIC_ACTIONS;

  return (<Subs.Button
    id="loginButton"
    text="Login"
    callback={sendAnalyticEvent(LOGIN, { action: LOGIN_ATTEMPT }, () => {
      const events = getAnalyticEventHistory();
      alert(`Generated event:\n${JSON.stringify(events[events.length - 1], null, 2)}`);
    })}
    recaptcha={{enabled: false}}
  />);
}

sendAnalyticEventSync(event, action)

This will create an analytics event synchronously.

import Subs from '@arc-core-components/feature_subscriptions';

const { CAMPAIGN_PAGE } = Subs.ANALYTIC_EVENTS;
const { CAMPAIGN_PAGE_VIEW } = Subs.ANALYTIC_ACTIONS;

sendAnalyticEventSync(CAMPAIGN_PAGE, { action: CAMPAIGN_PAGE_VIEW });

getAnalyticEventHistory()

Returns the analytics event history from wherever it is currently being stored.

Input Validation

These are functions you can import and use for input validation with custom forms or any other subscription related uses.

emailValidation(email:String)

Returns true if the email name contains only:

  • Uppercase (A-Z) and lowercase (a-z) English letters
  • Digits (0-9)
  • Characters ! # $ % & ' * + - / = ? ^ _ ` { | } ~
  • Character . (period, dot or fullstop) provided that it is not the first or last character and it will not come one after the other.

Returns true if the domain of the email address contains only:

  • Uppercase (A-Z) and lowercase (a-z) English letters
  • Digits (0-9)
  • Character . (period, dot or fullstop)

nameValidation(name:String)

Returns true if the name contains only:

  • Any characters except: '<>+_!@#$%^&*?.,' and numbers
  • No double spaces or dashes
  • Between 1 and 50 characters long

usDOBValidation(dob:String)

Returns true if DOB date format:

  • Matches the mm/dd/yyyy pattern
  • The date is before today (current date)

euDOBValidation(dob:String)

Returns true if the DOB date format:

  • Matches the dd/mm/yyyy pattern
  • The date is before today (current date)

addressValidation(address:String, required:Boolean = false)

Returns true if the address is required (defaults to false) and the address contains only:

  • Any characters except: "<>+_!@$%^&*?"
  • Between 1 and 256 characters long

cityValidation(city:String, required:Boolean = false)

Returns true if the city is required (defaults to false) and the city contains only:

  • Any characters except: "<>+_!@$%^&*?" and numbers
  • Between 1 and 100 characters long

stateValidation(state:String, required:Boolean = false)

Returns true if the state is required (defaults to false) and the state contains only:

  • Any characters except: "<>+_!#@$%^&*?" and numbers
  • Between 1 and 100 characters long

postalCodeValidation(code:String, required:Boolean = false)

Returns true if the postal code is required (defaults to false) and the postalcode contains only:

  • Any characters except: "<>+_!#@$%^&*?" and numbers
  • Between 1 and 100 characters long

displayNameValidation(displayName:String)

Returns true if the display name contains only:

  • Any characters
  • Between 1 and 100 characters long

phoneNumberValidation(phoneNumber:String)

Returns true if the phone number contains only numbers and dashes

Utilities

These are functions you can import and use for form validation callbacks or any other subscription utilities you might have a use for.

valueRequired(value:String|Object|Number)

Checks to see if the value is null or an empty string. Returns false if value is missing or empty object, otherwise returns true.

getHash()

Returns the hash tag from the browser window path and specifically ignores the window object for server side rendering. Useful for deep linkning in SPA applications.

isLoggedIn()

Checks whether or not someone is logged in. Returns the object from the cookie or local storage or false if not logged in.

sortBy(dataArray:Array, sortField:String|Number, ascending, fieldDataType:Array)

Sorts an array of objects by a specified field and then returns the sorted array of objects.

valuesMatch(value1:String|Object|Number, value2:String|Object|Number)

Checks to see if two values are the same type and the same content. Returns false if the values are different types or the content doesn't match.

randomID(min:Number = 100, max:Number = 9999)

Returns a random number from min to max, defaults to 100 - 9999.

defaultResponseText(messageID:String|Number)

Returns an array with all localized text and error messages if no messageID is given, otherwise returns the string or object for the given messageID object key.

newScript(scriptId:String, srciptSrc:String, resolveCallBack:Function, rejectCallback:Function)

Returns a promise after loading the async script by resolving the resolveCallback or rejecting with the rejectCallback. This is useful when you need to load an SDK script if you aren't using the NPM package for the retail or identity or sales SDK.

fullAddressValidation(address:{firstAddress, secondAddress, city, state, country, postalCode})

Provides default full address validation by matching the SDK requirements. Returns true if all the fields (except secondAddress) are populated OR all fields are empty, returns false otherwise.

isHTMLObject(string:String)

HTML object string validator, returns true if the string contains any HTML tag, false otherwise.

isoCodesValidation(list)

This hecks if the ISO values from the custom country array matches the A2-ISO. Returns false if at least one of the ISO values is not present in the countryAbbreviations array (A2 International Organization for Standardization).

countryAbbreviations:Array

This is an array of country code abbreviations.

defaultCountryList:Array

This is an array of default country codes to display in a country code dropdown. It includes the ISO code and the name of the country.

Localization

Localization is a single object that you can pass into the SPAs and some components in order to modify the text or error codes that are displayed to a user. This is especially useful if you need to display subscriptions in multiple languages. This object contains keys for display text and for error codes and setting custom country codes and regions.

Display Text

PropertyTypeDescription
signUpStringThe sign up header
signUpButtonStringThe sign up button
signInStringThe sign in header
signInButtonStringThe sign in button
emailStringThe email address input field label
emailPlaceholderStringThe placeholder for the email input address field
passwordStringThe label for the password input field
passwordPlaceholderStringThe placeholder for the password input field
forgotPasswordLinkStringThe text for the forgot password link
rememberMeCheckboxStringThe text next to the remember me checkbox
secondLastNameStringThe label for the second last name field
secondLastNamePlaceholderStringThe placeholder for the second last name field
loadingString, JSX ElementThe message or element displayed when something is loading
profileStringThe profile page header
firstNameStringThe label for the first name input field
lastNameStringThe label for the last name input field
displayNameStringThe label for the display name input field
dobStringThe label for the date of birth input field
genderStringThe label for the gender radio buttons
femaleStringThe text for the female gender radio button
maleStringThe text for the male gender radio button
nonConformingStringThe text for the non conforming gender radio button
preferNotToSayStringThe text for the perfer not to say gender radio button
statusBarIdentityObjectObject containing props used to configure the status bar for the IdentitySPA
statusBarIdentity.statusBarItemsObjectObject containing an property for each status bar object (object property). Each object property contains a display (string) property as well as an optional link property (to make it clickable)
statusBarRetailObjectObject containing props used to configure the status bar for the RetailSPA
statusBarRetail.statusBarItemsObjectObject containing an property for each status bar object (object property). Each object property contains a display (string) property as well as an optional link property (to make it clickable)
manageSubsPageTitleString, JSX ElementManage Subs Page - Title
manageSubStatusLabelString, JSX ElementManage Sub - Status Label
manageSubStatusInputPlaceholderStringManage Sub - Status Input Placeholder
manageSubStatusRenderInputContentFunctionManage Sub - Status Render Input Content
manageSubActionLabelString, JSX ElementManage Sub - Action Label
manageSubActionInputPlaceholderStringManage Sub - Action Input Placeholder
manageSubActionCancelReasonsArrayManage Sub - Action Cancel Reason Options List
manageSubActionBarCancelSubscriptionButtonContentString, JSX ElementManage Sub - Action Bar Cancel Subscription Button Content
manageSubActionBarSubmitButtonContentString, JSX ElementManage Sub - Action Bar Submit Button Content
manageSubActionBarCancelButtonContentString, JSX ElementManage Sub - Action Bar Cancel Button Content
manageSubActionBarRenewSubscriptionButtonContentString, JSX ElementManage Sub - Action Bar Renew Subscription Button Content
manageSubActionBarRenewSubscriptionRenderLabelContentString, JSX ElementManage Sub - Action Bar Renew Subscription Render Label Content
manageSubActionBarShowSubscriptionsButtonContentString, JSX ElementManage Sub - Action Bar Show Subscriptions Button Content
manageSubActionBarShowSubscriptionsLabelContentString, JSX ElementManage Sub - Action Bar Show Subscriptions Label Content
manageSubActionAlertSuccessContentString, JSX ElementManage Sub - Action Alert Success Content
manageSubActionAlertErrorContentString, JSX ElementManage Sub - Action Alert Error Content
manageSubActionAlertDurationNumberManage Sub - Action Alert Duration
manageSubLoadingIndicatorString, JSX ElementManage Sub - Loading Indicator
manageSubRenewSubscriptionCampaignIDString, NumberManage Sub - "Renew Subscription" CampaignID
manageSubShowSubscriptionsCampaignIDString, NumberManage Sub - "Show Subscription" CampaignID
manageSubRenewSubscriptionURLStringManage Sub - Renew Subscription URL
manageSubShowSubscriptionOptionsURLStringManage Sub - Show Subscription Options URL
orderHistoryTableTitleString, JSX ElementOrder History Table - Title to use on the table
orderHistoryTableDisplayConfigFunctionOrder History Table - Function that returns a configuration object used for providing table display parameters to child Table component
address1StringLabel for the first address line input field
address2StringLabel for the second address line input field
cityStringLabel for the city address input field
stateStringLabel for the state/region address input field
countryStringLabel for the country dropdown field
postalCodeStringLabel for the postal code input field
saveChangesStringText for save changes buttons
orderStringThe order header
removeStringThe remove item from cart button text
quantityStringThe quantity label on the order cart summary
taxStringThe tax label on the order cart summary
subtotalStringThe subtotal label on the order cart summary
totalStringThe total label on the order cart summary
checkoutStringThe text on the checkout button
SDKFailureStringMessage to display to users when the SDK does not load
userProfileFailureStringMessage to display to users when their profile doesn't load
profileUpdateSuccessTextStringMessage to display to users when their profile updates successfully
toggleStringAlternative 503 compliance text for tooggling a checkbox value
termsCheckboxStringText label to display beside the checkbox for accepting terms and conditions
termsAndConditionsStringText to display that shows the terms, privacy and GDPR policies. Includes special keywords that can be added to customize the text: {{termsUrl}}, {{termsLabel}}, {{privacyUrl}}, {{privacyLabel}}, {{GDPRUrl}}, {{GDPRLabel}}
termsLinkStringText to be substituted into the {{termsLink}} keyword in the termsAndConditions text
privacyLinkStringText to be substituted into the {{privacyLink}} keyword in the termsAndConditions text
GDPRLinkStringText to be substituted into the {{GDPRLink}} keyword in the termsAndConditions text
productCardGetOfferButtonTextStringText on the button of a product card
productPriceRadioButtonsLabelStringText on the product price radio button label
confirmationPageHeaderTextStringText that is shown on the payment confirmation form
confirmationPageSubHeaderTextStringSub-text that is shown on the payment confirmation form
confirmationPageRedirectLinkTextStringText that appears on the redirect link on the confirmation page
createOrderPhoneNumberLabelStringLabel that appears on the phone number input field
paymentOptionsStringLabel for payment processor radio buttons
paywallModalHeaderTextStringPaywall modal header text
paywallModalSubheaderTextStringPaywall modal sub-header text
paywallModalDescriptionTextStringDescription text on the paywall modal
paywallModalOfferTextStringText shown for the paywall offer to view a campaign
paywallModalAllOffersTextStringText to view all offers in a campaign
paywallModalSignInTextStringText to sign in from the paywall modal
paywallModalSignInMessageTextStringText to sign in if you already have an account
emailVerifiedSuccessStringText to show once an email has been verified
emailVerificationInProgressStringText to show while trying to verify the email address
signInRedirectToRegisterLinkTextStringText to redirect to create a new account
registerRedirectToSignInLinkTextStringText to redirect to sign in to an existing account
countryListArrayAn array of objects containing the ISO and name for each country ie. [{ ISO: "undefined", name: "N/A" }]

Error Codes

PropertyDescription
0009cMissing org headers
0014aAccess denied
0014bUnexpected server error
00016cProduct does not exist
00017cPricing strategy not found
00017dPricing rate not found
100005Max batch size is 100
100011Access denied
100012Only refresh token can be used to extend session
100014Account is locked
100015Account is disabled
100018Updates can only be made within 60 minutes of signing in
100022Failed to upload image
100023Display name already in use
100050Address line 1 is required
100052Address line 2 must be between 1 and 256 characters
100053Locality is required
100090First name must be between 1 and 50 characters
100096Invalid email
100101Nonce is required
100103New password does not meet strength requirements
100130Missing start date
100138Report in S3 not found
100200Old password does not meet strength requirements
100203New password does not meet strength requirements
110010Invalid username or password
130001ReCaptcha token invalid
130051Email address is not verified
200061Offer not found
200065Campaign not found
200066Offer not found
200101Campaign not found
200710No more rates available
300001Missing items
300002Empty items
300003SKU is missing
300004SKU is empty
300005Invalid character(s) in SKU
300006Invalid number of characters in SKU
300007Missing quantity
300008SKU not found in cart
300009Invalid email
300010Invalid character in phone number, allowed characters include 0-9 and -
300011Token is empty
300012Cart not found
300013Cart is empty
300014Payment provider not found
300015Order not found
300016Unexpected server error
300017Unable to retrieve response from Payment Express, contact tech support
300018Subscription not found
300019Access denied
300020Profile not found
300022Failed to delete image
300030Not found
300031Username not available
300033Nonce not found or expired
300036New password does not meet strength requirements
300037Password must be reset
300039Duplicate identity type
300040Invalid username or password
300041Email domain is blacklisted
300044At least one identity needs to remain on the user
300050Email already verified
300051Address line 1 must be between 1 and 256 characters
300052Email address cannot be empty
300053Email verification nonce required
300054Locality must be between 1 and 100 characters
300055Region must be between 1 and 100 characters
300056Postal code must be between 1 and 100 characters
300057Timed out while talking to Payment Express
300058Address type is required
300059Subscription not in a state that can be canceled
300060Attribute name is required
300061Attribute name must be between 1 and 30 characters
300062Attribute value is required
300063Attribute value must be between 1 and 1000 characters
300064Attribute type is required
300070Phone number is required
300071Phone number must be between 10 and 12 characters
300072Contact type is required
300073Parent subscription has been shared with max number of associates
300075Invalid email address format
300077Missing email address
300078Empty email address
300079Invalid SKU
300080Username is required
300081Username must be between 5 and 100 characters long
300082Password is required
300083Password does not meet strength requirements
300085Duplicate request to Payment Express
300090Configuration not found
300091Last name must be between 1 and 50 characters
300092Display name is required
300093Display name must be between 1 and 100 characters
300094Email must be between 1 and 100 characters
300095Email is required
300096Address line 1 must be between 1 and 256 characters
300097Address line 2 must be between 1 and 256 characters
300098Locality must be between 1 and 100 characters
300099Region must be between 1 and 100 characters
300100Country must be 2 characters
3001001User not found
3001002User not allowed to activate account
300101Maximum of 100 characters in address postal code
300102New password is required
300105Picture must be between 1 and 255 characters
300106Invalid date of birth format
300107legacy ID must be between 1 and 50 characters
300112Token is missing
300113Invalid character in token
300114Invalid token length
300117Billing address is required
300118Address type is required
300123Missing payment provider token
300124payment provider token may not be empty
300125Missing redeem code
300126Empty redeem code
300127Invalid character in first name
300128First name must be between 1 and 100 characters
300129Invalid character in last name
300130Last name must be between 1 and 100 characters
300131Missing end date
300133Missing report type
300136Report not found
300137Missing price code
300138Empty price code
300139Invalid price code
300140Invalid number of characters in price code
300141Too many character in campaign code
300142Invalid character(s) in campaign code
300151Missing client ID
300160Problem communicating with Spreedly
300161Unable to initialize session with Spreedly
300162Timed out while talking to Spreedly
300163Unable to retrieve response from Spreedly, contact tech support
300164Spreedly declined the transaction
300165Invalid address line 1
300167Invalid address locality
300168Invalid address region
300169Invalid address country
300171Invalid character in second last name
300172Second last name must be between 1 and 50 characters
300178Unexpected error communicating with PayPal
300180Invalid payment method expiration length
300181PayPal declined the transaction
300199Group email domain Not Found
300200Old password is required
300166Address 2 is invalid
300023DisplayName already in use
300201invalid character in reason or too many (2048)
300202New Password is required
300203New Password does not meet strength requirements
300204Invalid size
300205Invalid format
300300Username is required
300301Username must be between 5 and 100 characters long
3003jCountry must be 2 characters
300400Identity is required
300401Profile is required
300500User status is not provided
3007010Max number of contacts is 100
3007011Max number of addresses is 100
3007012Max number of attributes is 100
330011Invalid number of characters in phone number, use between 0 and 12 characters
330056Unable to initialize session with Payment Express
330059Parent subscription no longer active
330060Subscription already rescued
330061Calling user not allowed to cancel subscription
330062Calling user not allowed to rescue subscription
330072Requestor’s tenant does not match that of parent subscription
330081SKU not found
330090Invalid address type
330130Missing startDate
330138Report in S3 not found
330139Invalid price code
330165SlimPay declined transaction
330166Transaction was not processed by SlimPay
330167Transaction canceled by user
330180Customer declined PayPal billing agreement
330201Member is already in Group
requiredFieldField is required
passwordsDoNotMatchPasswords do not match
dobRequiredPlease enter your Date of Birth
googleSdkErrorGoogle SDK failed to load
googleSignOnErrorGoogle Sign In failed
facebookSdkErrorFacebook SDK failed to load
facebookSignOnErrorFacebook Sign In failed
userNotOfAgeYou must be over 14 years old

Country Codes

This is a property countryList in the localization object that takes an object with the mapping of all the ISO country codes and regions you would like to be available in your forms. By default uses the following format:

[
  {
    ISO: "undefined",
    name: "N/A",
    regions: [
      "N/A",
    ],
  },
]

Styles

Class NameDescription
wrapperClassesWrap individual forms and components within the SPA
headerClassesForm and component headers
errorClassesApply to error messages
errorHeadlineSizeH# size to use for error messages
successClassesApply to successful messages
labelClassesApply to input field labels
buttonClassesApply to buttons and submit input fields
inputClassesApply to input types of text and password
checkboxClassesApply to checkbox input types
dropdownClassesApply to select dropdowns
feedbackClassesApply to feedback messages tied directly to an input field for checking if required or has proper validation
radioWrapperClassesApply to the wrapper around all radio inputs in a series
radioContainerClassesWraps each individual radio label and input field
radioButtonClassesApply to a radio input field
radioLabelClassesApply to the label for each radio button
addressWrapperClassesWraps around all of the address fields
headlineImageWrapperClassesApplies to the wrapper around the campaign header image
headlineImageWrapperStylesApples inline styles to the header image
headlineImageSmBrkPntThe breakpoint for the small image size on the campaign header image in pixels
headlineImageMdBrkPntThe breakpoint for medium image sizes on the campaign header image in pixels
headlineImagePageTitleSizeThe H# size of the headline that overlays on top of the campaign header image
headlineImageTitleClassesClasses applied to the headline that overlays on top of the campaign header image
headlineImagePageSubTitleSizeThe H# size of the sub-headline that overlays on top of the campaign header image
headlineImageSubTitleClassesClasses applied to the sub-headline that overlays on top of the campaign header image
productCardsContainerWrapperClassesWraps all of the product cards in a campaign
productCardWrapperClassesApplies to the container around a product card in a campaign
productCardHeaderClassesApplies to a header in a product card
productCardHeaderSizeThe H# size of the header in a product card
productCardUnorderedListWrapperClassesClasses applied around all the items in an unordered list on a campaign product card
productCardUnorderedListItemClassesClasses applied to an idividual item in an unordered list on a campaign product card
productCardGetOfferButtonClassesClasses applied to the get offer button on a campaign product card
productCardLazyLoadingImageWrapperClassesClasses applied to the wrapper around lazy loaded images on a campaign product card
productCardLazyLoadingImageClassesClasses applied to the lazy loaded image on a campaign product card
productCardLazyLoadingImageLoaderClassesClasses applied to the wrapper around image loader on a campaign product card
productPriceRadioButtonsWrapperClassesApply to the wrapper around all radio price buttons on a campaign product card
productPriceRadioButtonsLabelClassesApply to the label on a radio price button on a campaign product card
productPriceRadioButtonsRadioButtonClassesApply to the price radio button on a campaign product card
productPriceRadioButtonsRadioLabelClassesApply to the label on a price radio button on a campaign product card
productRadioContainerClassesWraps a label and price radio button on a campaign product card
singleProductPriceFieldHeadlineSizeThe H# size for a product price headline on a campaign product card
singleProductPriceFieldHeadlineClassesApply to the product price headline on a campaign product card
disclaimerMessageHeadlineSizeThe H# size of the header for the disclaimer below a campaign product card
disclaimerMessageClassesApply to the disclaimer below a campaing product card
statusBarWrapperClassesWraps the items in a status bar
statusBarItemClassesApplies to each item in a status bar
statusBarDefaultClassesApplies to the un-selected items in a status bar
statusBarHighlightClassesApplies to the selected item in a status bar
statusBarItemSizeThe H# size of the text on a status bar item
confirmationPageWrapperClassesWraps the confirmation page contents
confirmationPageHeaderClassesApply to the headline on the confirmation form
confirmationPageHeaderSizeThe H# size of the header text on the confirmation form
confirmationPageSubHeaderClassesApply to the sub-headline on the confirmation form
confirmationPageSubHeaderSizeThe H# size of the sub-header text on the confirmation form
confirmationPageRedirectLinkClassesApply to the redirect link on the confirmation form
createOrderInfoWrapperClassesWraps the order information on the checkout form
cartWrapperClassesWraps the cart information on the checkout form
cartItemClassesApply to an item in the cart on the checkout form
orderWrapperClassesWraps the order item details on a checkout form
cartSummaryClassesWraps the summary section on the checkout form
manageSubsPageClassNameClasses added to "Manage Subs Page"
manageSubsPageManageSectionClassNameClasses added to "Manage Subs Page - Manage Section"
manageSubsPageHistorySectionClassNameClasses added to "Manage Subs Page - History Section"
manageSubsPageTitleClassNameClasses added to "Manage Subs Page - Title"
manageSubContainerClassNameClasses added to "Manage Sub - Container"
manageSubStatusContainerClassNameClasses added to "Manage Sub - Status Container"
manageSubStatusLabelClassNameClasses added to "Manage Sub - Status Label"
manageSubStatusCancelInitializedLabelClassNameClasses added to "Manage Sub - Status Cancel Initialized Label"
manageSubStatusInputWrapperClassNameClasses added to "Manage Sub - Status Input Wrapper"
manageSubStatusCancelInitializedInputWrapperClassNameClasses added to "Manage Sub - Status Cancel Initialized Input Wrapper"
manageSubStatusInputClassNameClasses added to "Manage Sub - Status Input"
manageSubStatusCancelInitializedInputClassNameClasses added to "Manage Sub - Status Cancel Initialized Input"
manageSubActionContainerClassNameClasses added to "Manage Sub - Action Container"
manageSubActionLabelClassNameClasses added to "Manage Sub - Action Label"
manageSubActionInputWrapperClassNameClasses added to "Manage Sub - Action Input Wrapper"
manageSubActionDropdownClassNameClasses added to "Manage Sub - Action Dropdown"
manageSubActionDropdownStyleStyles added to "Manage Sub - Action Dropdown"
manageSubActionBarClassNameClasses added to "Manage Sub - Action Bar"
manageSubActionBarNoneClassNameClasses added to "Manage Sub - Action Bar ('No Subscriptions' state)"
manageSubActionBarCancelClassNameClasses added to "Manage Sub - Action Bar ('Active Subscription' state)"
manageSubActionBarRenewClassNameClasses added to "Manage Sub - Action Bar ('Expired Subscription' state)"
manageSubActionBarCancelSubscriptionButtonClassNameClasses added to "Manage Sub - Action Bar Cancel Subscription Button"
manageSubActionBarCancelSubscriptionButtonStyleStyles added to "Manage Sub - Action Bar Cancel Subscription Button"
manageSubActionBarSubmitButtonClassNameClasses added to "Manage Sub - Action Bar Submit Button"
manageSubActionBarSubmitButtonStyleStyles added to "Manage Sub - Action Bar Submit Button"
manageSubActionBarCancelButtonClassNameClasses added to "Manage Sub - Action Bar Cancel Button"
manageSubActionBarCancelButtonStyleStyles added to "Manage Sub - Action Bar Cancel Button"
manageSubActionBarRenewSubscriptionButtonClassNameClasses added to "Manage Sub - Action Bar Renew Subscription Button"
manageSubActionBarRenewSubscriptionButtonStyleStyles added to "Manage Sub - Action Bar Renew Subscription Button"
manageSubActionBarRenewSubscriptionLabelClassNameClasses added to "Manage Sub - Action Bar Renew Subscription Label"
manageSubActionBarShowSubscriptionsButtonClassNameClasses added to "Manage Sub - Action Bar Show Subscriptions Button"
manageSubActionBarShowSubscriptionsButtonStyleStyles added to "Manage Sub - Action Bar Show Subscriptions Button"
manageSubActionBarShowSubscriptionsLabelClassNameClasses added to "Manage Sub - Action Bar Show Subscriptions Label"
manageSubActionAlertSuccessClassNameClasses added to "Manage Sub - Alert Success"
manageSubActionAlertErrorClassNameClasses added to "Manage Sub - Alert Error"
orderHistoryTableContainerClassNameClasses added to "Order History Table - Container"
orderHistoryTableTableClassNameClasses added to "Order History Table - Table"
orderHistoryTableTitleClassNameClasses added to "Order History Table - Title"
orderHistoryTableHeadingRowClassNameClasses added to "Order History Table - Heading Row"
orderHistoryTableHeadingColClassNameClasses added to "Order History Table - Heading Column"
orderHistoryTableHeadingColSortButtonClassNameClasses added to "Order History Table - Heading Column Sort Button"
orderHistoryTableHeadingColSortButtonIconClassNameClasses added to "Order History Table - Heading Column Sort Button Icon"
orderHistoryTableHeadingColSortButtonIconAscendingRendering (icon) to use for "Order History Table - Heading Column Sort Button Icon Ascending"
orderHistoryTableHeadingColSortButtonIconDescendingRendering (icon) to use for "Order History Table - Heading Column Sort Button Icon Descending"
orderHistoryTableRowClassNameClasses added to "Order History Table - Row"
orderHistoryTableRowHoverClassesClasses added to "Order History Table - Row Hover"
orderHistoryTableRowExpandedClassesClasses added to "Order History Table - Row Expanded"
orderHistoryTableRowCollapsedClassesClasses added to "Order History Table - Row Collapsed"
orderHistoryTableRowExpandedPanelClassesClasses added to "Order History Table - Row Expanded Panel"
orderHistoryTableRowDataClassNameClasses added to "Order History Table - Column"
orderHistoryTableRowToggleButtonColClassNameClasses added to "Order History Table - Toggle Button Column"
orderHistoryTableRowToggleButtonColStyleStyles added to "Order History Table - Toggle Button Column"
orderHistoryTableRowToggleButtonClassNameClasses added to "Order History Table - Toggle Button"
orderHistoryTableRowToggleButtonStyleStyles added to "Order History Table - Toggle Button"
orderHistoryTableRowToggleButtonExpandIconRendering to use for "Order History Table - Toggle Button Expand Icon"
orderHistoryTableRowToggleButtonCollapseIconRendering to use for "Order History Table - Toggle Button Collapse Icon"
orderHistoryTableRowExpandablePanelClassNameClasses added to "Order History Table - Row Expandable Panel"
orderHistoryTableRowExpandablePanelItemClassNameClasses added to "Order History Table - Row Expandable Panel Item"
orderHistoryTableRowExpandablePanelItemHeadingClassNameClasses added to "Order History Table - Row Expandable Panel Item Heading"
orderHistoryTableRowExpandablePanelItemDataClassNameClasses added to "Order History Table - Row Expandable Panel Item Body"
import Subscriptions from '@arc-core-components/feature_subscriptions';

<Subscriptions.IdentitySPA
  debug={false}
  config={{
    useCookies: true,
    autoLogin: true,
    secondLastName: false,
    recaptcha: {
      enabled: true,
      token: "your_site_key_here",
      position: "above",
      size: "invisible",
    },
    termsUrl: "http://my.site.com/terms",
    privacyUrl: "http://my.site.com/privacy",
    GDPRUrl: "http://my.site.com/gdpr",
  }}
  styles={{
    wrapperClasses: 'row col m-2',
    errorClasses: 'row text-danger',
    errorHeadlineSize: 4,
    successClasses: 'row text-success',
    buttonClasses: 'btn btn-primary w-100',
  }}
/>

Custom Forms

There will be times when one of the forms provided in the SPA does not meet business requirements or you need a custom solution. Here are some examples on how you can create a custom form using the existing form elements provided in core components. One thing to note with custom forms is that, depending on the use of the form, you may or may not be able to use it with the out of the box SPA provided in core components. Sometimes creating a custom form will also require that you create a custom spa.

Example

This creates a sample custom login form (username, password, remember me, lost password link, recaptcha) with analytics and custom fields that will allow you to control the form title, successful login url and whether or not to use cookies.

import React, { Component } from "react";
import PropTypes from "prop-types";
import Subscriptions from '@arc-core-components/feature_subscriptions';

const { LOGIN } = Subscriptions.ANALYTIC_EVENTS;
const { LOGIN_ATTEMPT, LOGIN_SUCCESS, LOGIN_FAILED } = Subscriptions.ANALYTIC_ACTIONS;
const { LOCAL } = Subscriptions.ANALYTIC_ENVIRONMENT;

/**
 * @class Login
 * @desc Creates a custom login form
 *
 * @return {Object} <Login /> React component
 */
export default class Login extends Component {
  /**
   * Default constructor
   * @param {Object} props - properties passed to the component
   *
   * @return null
   */
  constructor(props) {
    super(props);
    this.state = {
      email: null,
      password: null,
      error: null,
      rememberMe: true,
      disabled: false,
    };
  }

  /**
   * Set the state of the remember me option
   *
   * @param {Boolean} toggle - true|false to remember me
   * @return null, sets internal state
   */
  rememberMeCallback = (toggle) => {
    this.setState({ rememberMe: toggle });
  };

  /**
   * Callback for validating email addresses on this form
   *
   * @param {String} email - the email address to validate
   * @return {Boolean} the state of the validation
   */
  emailCallback = (email) => {
    if (emailValidation(email)) {
      this.setState({ email });
      return true;
    }

    this.setState({ email: null });
    return false;
  };

  /**
   * Checks to see if the email address has been entered or not
   *
   * @param {String} email - the email address to validate
   * @return {Boolean} the state of the validation
   */
  emailRequiredCallback = (email) => {
    if (!email) {
      this.setState({ error: "email required" });
      return true;
    }

    this.setState({ error: "" });
    return false;
  };

  /**
   * Callback to see if the password is valid or not
   *
   * @param {String} password - the password to validate
   * @return {Boolean} the state of the validation
   */
  passwordCallback = (password) => {
    if (password) {
      this.setState({ password });
      return true;
    }

    this.setState({ password: null });
    return false;
  };

  /**
   * Checks to see if the password has been entered or not
   *
   * @param {String} email - the email address to validate
   * @return {Boolean} the state of the validation
   */
  passwordRequiredCallback = (password) => {
    if (!password) {
      this.setState({ error: "password required" });
      return true;
    }

    this.setState({ error: "" });
    return false;
  };

  /**
   * Callback to see if the login form can be submitted or not
   *
   * @return {Object} status object
   */
  loginCallback = () => {
    const { email, password, rememberMe, error } = this.state;

    // use these settings from PB admin configuration
    const { useCookies, loginSuccessUrl } = this.props.customFields;

    if (error || !email || !password) {
      Subscriptions.sendAnalyticEventSync(LOGIN, { action: LOGIN_FAILED, environment: LOCAL });

      return {
        status: false,
        error,
      };
    }

    // disable the submit button
    this.setState({ disabled: true });

    // attempt to login
    Subscriptions.Identity("login", email, password, {
      rememberMe: rememberMe,
      cookie: useCookies,
      recaptchaToken: "YOUR_TOKEN_HERE",
    })
      .then(() => Subscriptions.sendAnalyticEventSync(LOGIN, { action: LOGIN_SUCCESS }, () => {
        // login successful, update the state of the form
        this.setState({ error: null });

        // forward them to an authenticated route
        window.location = loginSuccessUrl;
      }))
      .catch(result => Subscriptions.sendAnalyticEventSync(LOGIN, { action: LOGIN_FAILED, code: result.code }, () => {
        const errorCode = result.code.replace(/[\W_]+/g, "");

        // login failed, set the state to match the login error coming back and enable the login button again
        this.setState({ error: result.message, disabled: false });

        return {
          status: false,
          ...result,
        };
      }));

    // enable the sign in button
    return {
      disabled: false,
      status: false,
    };
  };

  /**
   * Render the login form
   *
   * @return {Object} sign in form
   */
  render() {
    const { disabled, rememberMe } = this.state;

    // get the title of the form from the PB admin fields
    const { formTitle } = this.props.customFields;

    return (
      <div className="wrapperClass">
        <Subscriptions.Header className="headerClass">{formTitle}</Header>
        <div className="error">{this.state.error}</div>
        <Subscriptions.EmailInput
          callback={this.emailCallback}
          requiredCallback={this.emailRequiredCallback}
        />
        <Subscriptions.PasswordInput
        callback={this.passwordCallback}
        requiredCallback={this.passwordRequiredCallback}
        />
        <Subscriptions.ForgotPasswordLink />
        <Subscriptions.SignInButton
          disabed={disabled}
          callback={this.loginCallback}
        />
        <Subscriptions.RememberMeCheckbox defaultChecked={rememberMe} />
      </div>
    );
  }
}

Login.propTypes = {
  customFields: PropTypes.shape({
    formTitle: PropTypes.string.tag({
      defaultValue: 'Login',
      name: 'Login Form Title',
      group: 'Text',
    }),
    loginSuccessUrl: PropTypes.string.tag({
      defaultValue: '/profile',
      name: 'Login Success URL',
      group: 'Settings',
    }),
    useCookies: PropTypes.bool.tag({
      defaultValue: false,
      name: 'Use Cookies?',
      group: 'Settings',
    }),
};

Login.defaultProps = {
  customFields: {
    formTitle: "Login",
    loginSuccessUrl: "/profile",
    useCookies: false,
  },
};

Custom SPA

Sometimes you need to make customizations to the workflow provided in our Identity or Retail SPAs or you want to create your own SPA. Here is an example of how you can create a custom SPA using a mix of your own custom forms and forms provided for you in core components.

Example

import React, { Fragment } from "react";
import PropTypes from "prop-types";
import {
  HashRouter, Switch, Route, Redirect,
} from "react-router-dom";
import Subscriptions from '@arc-core-components/feature_subscriptions';

import Profile from 'your-custom-profile-component';
import Login from 'your-custom-login-component';

/**
* @class CustomIdentitySPA
*/
export default class CustomIdentitySPA extends React.Component {
  /**
   * Default constructor
   */
  constructor(props) {
    super(props);

    // figure out if user is logged in or not
    const user = Subscriptions.isLoggedIn();

    this.state = {
      /**
       * we recommend keeping the user'ss data in a global state
       * or react context so you can pass it to any of the forms
       * in your SPA without having to reload it each time
      */
      identity: user || {},

      /**
       * You can create a custom function to update global state
       * shared between all forms or use react context
       */
      update: (key, value) => {
        this.setState({ [key]: Object.assign(this.state[key], value) });
      },
    };
  }

  /**
   * Renders the SPA using HashRoutes to navigate, using regular
   * routes may conflict with PB Admin's routing configuration.
   * You can add as many routes as you would like.
   */
  render() {
    return (
      <HashRouter>
        <Switch>
          <Route
            exact
            path="/profile"
            render={(props) => (Subscriptions.isLoggedIn()
              ? <Profile {...this.state} {...props} />
              : <Redirect to="/login" />
            )}
          />
          <Route
            exact
            path="/sign-out"
            render={() => <Subscriptions.SignOutFormSPA {...this.state} signOutUrl="/login" />}
          />
          <Route
            path="*"
            render={(props) => <Login {...this.state} {...props} />}
          />
        </Switch>
      </HashRouter>
    );
  }
}

IdentitySPA.propTypes = {};

FAQs

Package last updated on 14 Oct 2020

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts