2.3.6 • Published 9 months ago

@dotdev/reactive-rewards v2.3.6

Weekly downloads
-
License
UNLICENSED
Repository
gitlab
Last release
9 months ago

Reactive Apparel21 Rewards

The front end react library for the AP21 rewards integration.

Install

To install simply run npm install @dotdev/reactive-rewards

Setup Shopify store

There are a few requirements for this integration. This integration requires Shopify scripts therefore it is only available to Shopify Plus partners.

  1. Install the Shopify Scripts and create a new line item script with this script. The Shopify script will apply any rewards to cart and reduce benefits price down to 0.
  2. Create a new private app with storefront access to unauthenticated_read_product_listings, unauthenticated_read_product_tags, unauthenticated_read_product_inventory. This will be used to fetch reward and gift products asynchronously.c67a5b66: #shopify-script "Shopify Script"
  3. Create a reward product. This product will need to have a price of 0.

Usage

Once installed the Loyalty components can be imported like this.

import * as Loyalty from "@dotdev/reactive-rewards"

Provider

All loyalty components should be wrapped within the Provider component. The provider component takes the Shopify customer information and uses it to request the Apparel21 customer. The Apparel21 customer is then passed into the child components. It also takes other store specific configurations.

<Loyalty.Provider
  customer={account.customer}
  rewardId={32843578376280}
  url={'https://connector-staging.cable-integration.io'}
  storefront={{
    key: '41e72449d9ae377baa2363774f504fd2',
    url: window.theme.permanentDomain,
  }}
  theme={{
    typography: {
      headings: {
        h3: {
          fontFamily: 'Chronicle, Helvetica Neue, Arial, sans-serif',
          fontSize: '2rem'
        },
        h4: {
          fontSize: '1.25rem'
        }
      }
    },
    colors: {
      primary: '#000',
      secondary: '#fff',
    },
    spacing: {
      vertical: 5,
      horizontal: 5
    },
    container: {
      width: 1440,
    },
    image: {
      borderStyle: 'solid',
      borderWidth: 1,
    },
    button: {
      borderStyle: 'solid',
      borderWidth: 1,
      textTransform: 'uppercase',
      letterSpacing: '0.075rem',
      fontSize: '1rem',
      fontWeight: 600,
    },
  }}
>
  <Loyalty.Benefits
    title={"Gifts & Rewards"}
    redeemable
  />
</Loyalty.Provider>
propdescriptionrequired
customerAn object representing Shopify customer information containing first_name, last_name, token, id. Read below about how to generate a token.yes
rewardIdA variant id representing a reward placeholder product in Shopify.yes
urlAn optional url prefix for using a staging integration or changing the proxy urlno
storefrontAn object that takes the storefront api key and the store url.yes
themeAn object representing the styles that you would like to pass to the components. Any of the keys you provide will overwrite the default styling but you do not need to provide all of them.no

Generating a Token

For security reasons Liquid should be used to generate a token so that the secret is not exposed to the front end. Each customer will have a unique id and each store will have a different secret by combining the 2 with hmac_sha256 we can create a secret token for fetching the Apparel21 user.

{{ customer.metafields.ap21.person_id | hmac_sha256: settings.loyalty_secret | json }}

You may want to store the secret in the theme settings, especially if the store has multiple regions.

{
  "name": "Loyalty",
  "settings": [
    {
      "type": "text",
      "id": "loyalty_secret",
      "label": "Loyalty secret"
    }
  ]
},

Basic Components

There are a two base components (Account and Benefits) which are designed to work "out of the box" and reduce the amount of time it takes to get started. These components can be customised simply by using the theme prop on the Provider component. If you need to customise the layout of the component you can use the render prop.

Account

Displays basic account information such as current tier, the spend to the next tier, the date they achieved the current tier. It also has an optional render prop so that you can fully customise the structure and layout of this component.

Benefits

Displays the current rewards and benefits to the customer. When the redeemable prop is used it will change the layout to display buttons which will allow the gifts to be redeemed. The redeemable prop can technically be used anywhere on the site but would typically be used on the cart page.

Advanced components

If you want to have complete control over the rendering of the components there are two options. Either use the Consumer component or hooks. If you would like to use hooks read below.

Consumer

Example

<Loyalty.Provider
  customer={customer}
  rewardId={32843578376280}
  url={'https://connector-staging.cable-integration.io'}
  storefront={{
    key: '41e72449d9ae377baa2363774f504fd2',
    url: window.theme.permanentDomain,
  }}
>
  <Loyalty.Consumer>
    {({ account }) => {
      if (!account) {
        return <React.Fragment />
      }
      const name = account.tier_name as 'Cotton' | 'Merino' | 'Cashmere'
      const tier = tiers[name]
      return (
        <div className="w-1/3 p-1">
          <div className="bg-grey-100">
            <div className="p-4">
              <p className="font-heading text-2xl tracking-widest mt-1">
                <span className="uppercase">{name}</span> tier
              </p>
              <ul className="mb-2 list-disc uppercase text-xs">
                {tier.features.split("\n").map((item) => (
                  <li key={item}>
                    {item}
                  </li>
                ))}
              </ul>
              <h3 className="font-heading italic">
                Annual Spend<br/>
                {tier.spend}
              </h3>
            </div>
          </div>
        </div>
      )
    }}
  </Loyalty.Consumer>
</Loyalty.Provider>

The consumer is provided with the context as a render prop.

Hooks

useAccount

Get the Apparel21 account

useBenefits

Get the Available rewards

useCart

Get the Shopify cart

Shopify Script

### Begin loyalty ###

# Check if cart contains ordinary product
cartContainsOrdinaryProduct = false
Input.cart.line_items.each do |line_item|
  if (
    !line_item.properties["_gift_id"]
  ) then
    cartContainsOrdinaryProduct = true
    break
  end
end

# Calculate subtotal for reward eligibility (inc discount codes)
rewardSubtotal = Input.cart.subtotal_price
if Input.cart.discount_code && !Input.cart.discount_code.rejected?
  if Input.cart.discount_code.is_a?(CartDiscount::Percentage)
    rewardSubtotal -= (rewardSubtotal * (Input.cart.discount_code.percentage/ 100))
  elsif Input.cart.discount_code.is_a?(CartDiscount::FixedAmount)
    rewardSubtotal -= Input.cart.discount_code.amount
  end
end

# Gifts only allowed for carts with an ordinary product
appliedGiftIds = []
Input.cart.line_items.each do |line_item|
  next unless line_item.properties["_gift_id"]

  if !cartContainsOrdinaryProduct || appliedGiftIds.include?(line_item.properties["_gift_id"])
    line_item.change_properties({ "remove" => true }, message: "Remove")
  end

  appliedGiftIds.push(line_item.properties["_gift_id"])
end
Input.cart.line_items.delete_if { |item| item.properties["remove"] }

rewardAmount = Money.zero()

Input.cart.line_items.each do |line_item|
  product = line_item.variant.product
  if product.product_type == "Loyalty Reward" then
    rewardAmount += Money.new(cents: line_item.properties["reward_amount"].to_i)
  end
  if line_item.properties["_gift_id"]
    line_item.change_line_price(line_item.line_price - line_item.variant.price, message: "Gift Redemption")
  end
end

Input.cart.line_items.each do |line_item|
  product = line_item.variant.product
  if (product.product_type != "Loyalty Reward" && product.product_type != "Gift Card") then
    if (line_item.line_price.cents < rewardAmount.cents)
      rewardAmount -= line_item.line_price
      line_item.change_line_price(Money.zero(), message: "Reward Redemption")
    else
      line_item.change_line_price(line_item.line_price - rewardAmount, message: "Reward Redemption")
      rewardAmount = Money.zero()
    end
  end
end

### End loyalty ###
Output.cart = Input.cart
2.3.6

9 months ago

2.3.2

11 months ago

2.3.1

11 months ago

2.3.4

11 months ago

2.3.3

11 months ago

2.3.5

11 months ago

2.3.0

2 years ago

2.2.0

3 years ago

2.1.0

4 years ago

2.0.3

4 years ago

2.0.2

4 years ago

2.0.1

4 years ago

2.0.0

4 years ago

1.0.3

4 years ago

1.0.2

4 years ago

1.0.1

4 years ago

1.0.0

4 years ago

1.0.3-alpha

4 years ago

1.0.2-alpha

4 years ago

1.0.1-alpha

4 years ago

1.0.0-alpha

4 years ago