# Integrating EasyPoints

WARNING

The EasyPoints integration guide assumes intermediate level knowledge of Liquid, HTML, CSS, and JavaScript. This guide may not be the exact solution for integrating your store. If you are new to Shopify themes, it might be better to contact us at easypoints.jp (opens new window) for a custom integration by our in-house engineers.

# Pre-Integration

Download EasyPoints boilerplate to your project folder:

This includes files which will help you integrate EasyPoints to your theme easier.

TIP

You can use Git to keep track of the changes you are making to your theme. We recommend to make one commit per added EasyPoints feature.

# Update theme.liquid file

Before you begin inserting EasyPoints point snippets into your liquid files, make sure that the following codes are included in the theme.liquid file.

You should find the snippet below at the bottom of your html header:



 
 



{%- comment -%} START EASYPOINTS - DO NOT MODIFY! 変更しないでください! INFO @ https://bit.ly/2Dn7ESM {%- endcomment -%}
  {%- unless shop.metafields.loyalty.easy_points_attributes.value.stealth_mode -%}
    {{ 'easy_points.css' | asset_url | stylesheet_tag }}
    {{ 'easy_points.js' | asset_url | script_tag }}
  {%- endunless -%}
{%- comment -%} END EASYPOINTS {%- endcomment -%}

This file should be inserted automatically into your theme.liquid file when you installed EasyPoints to your store.

Insert the additional file imports for integrations alongside the existing imports. The final result should look something like this:



 
 






{%- comment -%} START EASYPOINTS - DO NOT MODIFY! 変更しないでください! INFO @ https://bit.ly/2Dn7ESM {%- endcomment -%}
  {%- unless shop.metafields.loyalty.easy_points_attributes.value.stealth_mode -%}
    {% render 'easy_points_metafield_script' %}
    {{ 'easy_points.css' | asset_url | stylesheet_tag }}
    {{ 'easy_points.js' | asset_url | script_tag }}
    {{ 'easy_points_integration.css' | asset_url | stylesheet_tag }}
    {{ 'easy_points_integration.js' | asset_url | script_tag }}
  {%- endunless -%}
{%- comment -%} END EASYPOINTS {%- endcomment -%}

And make sure the following code is inserted at the bottom of your html body:



 
 



{%- comment -%} START EASYPOINTS - DO NOT MODIFY! 変更しないでください! INFO @ https://bit.ly/2Dn7ESM {%- endcomment -%}
  {%- unless shop.metafields.loyalty.easy_points_attributes.value.stealth_mode -%}
    {% include 'easy_points' %}
    {% include 'easy_points_widget' %}
  {%- endunless -%}
{%- comment -%} END EASYPOINTS {%- endcomment -%}

easy_points_integration files are there to help you with the integration. You can use the easy_points_integration.css when you want to change the appearance of the point displays and you will need to use easy_points_integration.js when points displays or the redeem button is not working depending on how your theme is designed.

Usually, you will have to manipulate the JavaScript file when your products have variants. If the product variants, when selected, refreshes the whole page, there will be no problem. But, if the variants involves DOM manipulation, you will have to write some JavaScript (in easy_points_integration.js) to refresh EasyPoints accordingly.

# Product Points

In order to start displaying points where you want to, you first need to identify the location where you want to render the product points value reward with your theme.

Examples of common locations for rendering product points:

main-product.liquid

{% render 'easy_points_product_points' %} is used to render product points.

Default class for product points: "easy-points__product-points"

Input:



 



{%- comment -%} START EASYPOINTS - DO NOT MODIFY! 変更しないでください! INFO @ https://bit.ly/2Dn7ESM {%- endcomment -%}
  {%- unless shop.metafields.loyalty.easy_points_attributes.value.stealth_mode -%}
    {% render 'easy_points_product_points' %}
  {%- endunless -%}
{%- comment -%} END EASYPOINTS {%- endcomment -%}

Output:

The {%- comment -%} START/END EASYPOINTS {%- endcomment -%} allows the snippet to be recognized as EasyPoints functions and the {%- unless shop.metafields.loyalty.easy_points_attributes.value.stealth_mode -%} allows the points to be in stealth mode depending on the app settings.

We use this class convention class="easy-points__product-points to modify styling in easy_points_integration.css file.

# Account Balance & Birthday Forms

Insert {% render 'easy_points_account_balance' %} snippet in account.liquid where you want to display easypoints.

Input:


 


{%- comment -%} START EASYPOINTS - DO NOT MODIFY! 変更しないでください! INFO @ https://bit.ly/2Dn7ESM {%- endcomment -%}
  {% render 'easy_points_account_balance' %}
{%- comment -%} END EASYPOINTS {%- endcomment -%}

 


{%- comment -%} START EASYPOINTS - DO NOT MODIFY! 変更しないでください! INFO @ https://bit.ly/2Dn7ESM {%- endcomment -%}
  {% render 'easy_points_note_form', class_input: '', class_button: '' %}
{%- comment -%} END EASYPOINTS {%- endcomment -%}

 


{%- comment -%} START EASYPOINTS - DO NOT MODIFY! 変更しないでください! INFO @ https://bit.ly/2Dn7ESM {%- endcomment -%}
  {% render 'easy_points_register_fields', show_label: '', class_label: '', class_input: '' %}
{%- comment -%} END EASYPOINTS {%- endcomment -%}

Output:

If your account.liquid design is simple, you won't need to change much setting for the point display to stay consistent with your theme's style.

If you want to edit the css, you can assign your desired classes in easy_points_account_balance.liquid file and modify classes in your easy_points_integration.css file.

In order to check if your point display is functioning correctly, you can allocate points to yourself manually (opens new window).

# Cart Item Points

Like the product points .liquid file, you first need to identify where your main cart.liquid file is.

Examples of common locations for rendering cart points:

main-cart-footer.liquid

Then insert the {% render 'easy_points_product_points', item: item %} snippet where you want to display points for each product in your cart.

Make sure the item: item_name is the correct item_name used to render your product prices.

If points appear as NaN points or - points, you may need to do some debugging using the easy_points_integration.js file. See Cart Item Points JS Debug.

Input:

{%- comment -%} START EASYPOINTS - DO NOT MODIFY! 変更しないでください! INFO @ https://bit.ly/2Dn7ESM {%- endcomment -%}
  {%- unless shop.metafields.loyalty.easy_points_attributes.value.stealth_mode -%}
    <span class="easy-points__cart-item-points">
      {% render 'easy_points_product_points', item: item %}
    </span>
  {%- endunless -%}
{%- comment -%} END EASYPOINTS {%- endcomment -%}

Output:

# Cart Point Redeem Button & Total Points Earned

Next, we will insert two snippets, one for redeeming points and one for displaying total points earned from the purchase.

Input (Redeem Button): Insert this snippet above cart Total Price display



 
 



{%- comment -%} START EASYPOINTS - DO NOT MODIFY! 変更しないでください! INFO @ https://bit.ly/2Dn7ESM {%- endcomment -%}
  {%- unless shop.metafields.loyalty.easy_points_attributes.value.stealth_mode and customer -%}
    {% render 'easy_points_redemption_form', hide_points_form: true %}
    {% render 'easy_points_redemption', class_button: 'btn btn--secondary' %}
  {%- endunless -%}
{%- comment -%} END EASYPOINTS {%- endcomment -%}

Input (Total Points): Insert this snippet below cart Total Price display





 


 





{%- comment -%} START EASYPOINTS - DO NOT MODIFY! 変更しないでください! INFO @ https://bit.ly/2Dn7ESM {%- endcomment -%}
  {%- unless shop.metafields.loyalty.easy_points_attributes.value.stealth_mode -%}
  <div class="easy-points__subtotal-points">
    <span class="easy-points__cart-title">
      {{ 'easypoints.points_earned_total' | t }}
    </span>
    <span class="easy-points__cart-points">
      {% render 'easy_points_total_points', price: cart.total_price %}
    </span>
  </div>
  {%- endunless -%}
{%- comment -%} END EASYPOINTS {%- endcomment -%}

Outputs:

For the redeem button to function correctly and for the discount prices to be updated when the point is applied, there are some additional steps you will be required to make:

You first need to create a div <div class="easy-points__subtotal" data-loyal-target="subtotal"> around the total price and the total points earned displays.

Then, insert the following data values inside the container of the total price display. This allows price modification when discount is applied:

data-loyal-target="total_price"
data-loyal-total-price="{{ cart.total_price }}"

Example:

 


 
 










 

<div class="easy-points__subtotal" data-loyal-target="subtotal">
  <span>小計:</span>
  <span
    data-loyal-target="total_price"
    data-loyal-total-price="{{ cart.total_price }}"
  >
    {{ cart.total_price | money_without_trailing_zeros }}
  </span>

  {%- comment -%} START EASYPOINTS - DO NOT MODIFY! 変更しないでください! INFO @ https://bit.ly/2Dn7ESM {%- endcomment -%}
    {%- unless shop.metafields.loyalty.easy_points_attributes.value.stealth_mode -%}
      {{ 'easypoints.points_earned_total' | t }}:
      {% render 'easy_points_total_points', price: cart.total_price %}
    {%- endunless -%}
  {%- comment -%} END EASYPOINTS {%- endcomment -%}
</div>

# Cart Subtotal Currency Display

Lastly, IF your shop has money with currency format you will have to insert option_selection.js snippet in your theme.liquid file above the EasyPoints integration files:

{%- comment -%} START EASYPOINTS - DO NOT MODIFY! 変更しないでください! INFO @ https://bit.ly/2Dn7ESM {%- endcomment -%}
  {%- if request.page_type == 'cart' -%}
    {{ 'option_selection.js' | shopify_asset_url | script_tag }}
  {%- endif -%}
{%- comment -%} END EASYPOINTS {%- endcomment -%}

You may also need to include the following at the bottom of your html body depending on your theme money_format settings:

{%- comment -%} START EASYPOINTS - DO NOT MODIFY! 変更しないでください! INFO @ https://bit.ly/2Dn7ESM {%- endcomment -%}
  {%- unless shop.metafields.loyalty.easy_points_attributes.value.stealth_mode -%}
    <script>
      if (EasyPointsData) {
        EasyPointsData.shop.money_format = "{{ shop.money_with_currency_format }}";
      }
    </script>
  {%- endunless -%}
{%- comment -%} END EASYPOINTS {%- endcomment -%}

# Cart Item Points JS Debug

If points appear as NaN points or - points, you may need to do some debugging using the easy_points_integration.js file.

To avoid all problems, when you are designing your cart, we recommend using a design as simple as possible. For example, when you are using variants for product quantity, if the cart does not reload the page completely, the EasyPoints will likely to have JavaScript issues.

You can mitigate this issue all together if the cart page is reloaded for each change made in your cart. This is not the case if your cart design is dynamic.

Another source of the problem is when loading cart page, your cart theme design involves multiple DOM manipulations which may not trigger the EasyPoints to refresh.

If this is the case, you will have to write a JavaScript code with mutation observers to observe changes and excute the functions below to reset all EasyPoints:

EasyPoints.reset({});
EasyPoints.Register.run();

WARNING

This will be difficult

In your easy_points_integration.js change DEBUG: false to DEBUG true:




 






var EasyPoints = {

  Debug: {
    DEBUG: true,

    print: function(msg, type = 'info') {
      if (!this.DEBUG) {
        return;
      }

Example of JavaScript code in easy_points_integration.js

window.addEventListener('DOMContentLoaded', function() {
var pricingContainer = document.querySelector('#productPrice-product-template');

if (pricingContainer) {
 var variantsCallback = function(mutationsList, observer) {
   var update = false;

   for (var mutation of mutationsList) {
     console.log(mutation);
     if (mutation.type === 'childList' && mutation.target.classList.contains('product-price')) {
       var price = EasyPoints.Points.getPriceFromEl(mutation.target);

       if (price) {
         var pointsNode =
           mutation.target
             .closest('.easypoints-product-container')
             .querySelector('.easy-points [data-loyal-target="point-value"]');

         EasyPoints.Points.setCurrencyCost(pointsNode, { price: price });

         update = true;
       }
     }
   }

   if (update) {
     updateLoyaltyTargets();
   }
 };

 (new MutationObserver(variantsCallback))
   .observe(pricingContainer, {
     attributes: true,
     childList: true,
     subtree: true
   });
 }

  var path = this.window.location.pathname;
  var re = /\/cart/i;

  if (!path.match(re)) {
    return;
  }

  EasyPoints.reset({});
  EasyPoints.Register.run();

  var cartNode = document.querySelector('form[action="/cart"]');

  if (cartNode) {
    var callback = function(mutationsList, observer) {
      for (var mutation of mutationsList) {
        if (mutation.type === 'childList' && mutation.target == cartNode) {
          EasyPoints.reset({});

          document.querySelectorAll('[data-loyal-target="subtotal"]')
            .forEach(node => {
              var price = EasyPoints.Points.getPriceFromEl(node, '[data-loyal-target="total_price"]');
              EasyPoints.Points.setCurrencyCost(
                node.querySelector('[data-loyal-target="total-points-value"]'),
                { price: price }
              );
            });

          EasyPoints.Points.insertTotalPoints(document);
          EasyPoints.Points.resetTargets();
          EasyPoints.Cart.setRedemptionForm();

          break;
        }
      }
    };

    (new MutationObserver(callback))
      .observe(cartNode, {
        attributes: false,
        childList: true,
        subtree: true
      });
  }
});