@okendo/shopify-hydrogen 2.6.1 → 2.6.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -8,8 +8,9 @@ This package brings Okendo's [Reviews widgets](https://okendo.io/reviews) and [L
8
8
 
9
9
  ## Requirements
10
10
 
11
- - A Shopify store with a [Hydrogen](https://hydrogen.shopify.dev/) storefront and [Okendo](https://apps.shopify.com/okendo-reviews) installed and configured.
11
+ - You need a Shopify store with a [Hydrogen](https://hydrogen.shopify.dev/) storefront and [Okendo](https://apps.shopify.com/okendo-reviews) installed and configured.
12
12
  - For existing merchants, your store must be using Okendo's Widget Plus widgets. [Contact us](mailto:support@okendo.io) if it's not the case, it's free to upgrade.
13
+ - **[Contact us](mailto:support@okendo.io) to enable the Storefront Metafields feature on your account.** This is necessary to enable server-side rendering using Shopify metafields.
13
14
 
14
15
  ## Demo Store
15
16
 
@@ -488,6 +489,8 @@ export default function Homepage() {
488
489
 
489
490
  To include Loyalty Widgets in your Shopify Hydrogen store, you will need to make the following changes:
490
491
 
492
+ These are the instructions for stores which use the **Customer Account API** for customer login. If you are using the **Storefront API** for customer login then please skip ahead to [Storefront API Login](#storefront-api-login) below
493
+
491
494
  1. Add `customerAccessToken: await args.context.customerAccount.getAccessToken(),` to your `loader` function, this will be used to log your customer into the Loyalty App.
492
495
 
493
496
  2. Add `okendoProducts: ['reviews', 'loyalty'],` as a property to `getOkendoProviderData` in your `loader` function, alongside the existing `context` and `subscriberId` arguments.
@@ -521,6 +524,26 @@ return defer({
521
524
 
522
525
  If your Okendo Loyalty Settings are [correctly set up](https://support.okendo.io/en/collections/8270193-okendo-loyalty) and your program has launched, the Loyalty Floating Widget will now appear on your store.
523
526
 
527
+ ### Storefront API Login
528
+
529
+ Instead of passing `customerAccessToken` into the `OkendoProvider` as above, you will need to pass in two other properties:
530
+
531
+ - `storefrontCustomerAccessToken`: When the user logs in with a username and password, the response from Shopify should look like `{ customerAccessToken: { accessToken: string }}`. The value of the `accessToken` string is what we require for the `storefrontCustomerAccessToken`, but the method of accessing it in your project's `loader` function will differ depending on your setup.
532
+
533
+ - `storefrontAccessToken`: a static value which is most likely in your environment variables as `PUBLIC_STOREFRONT_API_TOKEN` and being used for your `X-Shopify-Storefront-Access-Token` header. If not, it can usually be found in `Shopify Admin -> Sales channels -> Hydrogen/Headless -> Pick your storefront -> Storefront Settings -> Storefront API -> Public access token (Use this token to access the Storefront API in client-side contexts)`
534
+
535
+ Your `OkendoProvider` component should now look something like this:
536
+
537
+ ```tsx
538
+ <OkendoProvider
539
+ okendoProviderData={data.okendoProviderData}
540
+ storefrontCustomerAccessToken={data.storefrontCustomerAccessToken}
541
+ storefrontAccessToken={data.storefrontAccessToken}
542
+ >
543
+ ...
544
+ </OkendoProvider>
545
+ ```
546
+
524
547
  ## Dedicated Loyalty Page
525
548
 
526
549
  Add `<OkendoLoyaltyEmbeddedWidget />` to any components/pages where you wish to have the Dedicated Loyalty Page appear.
package/dist/cjs/index.js CHANGED
@@ -1 +1 @@
1
- "use strict";var e=require("react-router"),t=require("react"),n=require("@shopify/hydrogen");const r=/^[0-9]*$/,s="app--1576377";function a(e){if(e)return`shopify-${r.test(e)?e:e.split("/").slice(-1)[0]}`}const o="cdn-static.okendo.io",i=({okendoProviderData:e,productUrlFormatter:r,cdnDomain:s})=>{const a=t.useRef(!1),i=t.useRef(!1);if(t.useEffect((()=>{if(e&&e.loyaltySettings&&!1===a.current){const t=document.createElement("script");t.src=`https://${s||o}/loyalty/js/init-onsite.js`,document.head.appendChild(t);const n=document.createElement("script");n.type="application/json",n.id="oke-loyalty-settings";const r=e.loyaltySettings?e.loyaltySettings.replaceAll(/<\/?script.*?>/g,""):"";n.innerHTML=r,document.head.appendChild(n),a.current=!0}}),[e,s]),t.useEffect((()=>{if(e&&!i.current){const e=document.createElement("script");e.src=`https://${s||o}/reviews-widget-plus/js/okendo-reviews.js`,document.head.appendChild(e),i.current=!0}}),[e,s]),!e)return null;const{reviewsHeaderConfig:d,cssVariables:l,customCss:c,preRenderStyleTags:u,starSymbols:p}=e,m=(l??"").replace('<style id="oke-css-vars">',"").replace("</style>",""),y=c?c.replace('<style id="oke-reviews-custom-css">',"").replace("</style>",""):"";return t.createElement(t.Fragment,null,t.createElement(n.Script,{id:"oke-reviews-settings",type:"application/json",dangerouslySetInnerHTML:{__html:JSON.stringify(d)}}),t.createElement("style",{id:"oke-css-vars",dangerouslySetInnerHTML:{__html:m}}),y&&t.createElement("style",{id:"oke-reviews-custom-css",dangerouslySetInnerHTML:{__html:y}}),t.createElement(n.Script,{type:"text/javascript",dangerouslySetInnerHTML:{__html:`window.okeProductUrlFormatter = ${"function"==typeof r?r.toString():"string"==typeof r?r:"(product) =>\n product && product.productHandle\n ? \"/products/\" + product.productHandle + (product.variantId ? '?variantId=' + product.variantId : '')\n : undefined"}`}}),u&&t.createElement("div",{dangerouslySetInnerHTML:{__html:u}}),p&&t.createElement("div",{dangerouslySetInnerHTML:{__html:p}}))};const d=({style:e,className:n,dataAttributes:r,metafieldContent:s=""})=>{const a=t.useRef(null),o=t.useRef(!1),i=function(e){const n=t.useRef();return t.useEffect((()=>{n.current=e})),n.current}(r),d=()=>{a.current&&(window.okeWidgetApi.initWidget(a.current),o.current=!0)};return t.useEffect((()=>{if(!i||r["data-oke-widget"]!==i["data-oke-widget"]||r["data-oke-star-rating"]!==i["data-oke-star-rating"]||r["data-oke-reviews-product-id"]!==i["data-oke-reviews-product-id"]||!o.current)return window.okeWidgetApi&&a.current?d():document.addEventListener("oke-script-loaded",d),()=>{document.removeEventListener("oke-script-loaded",d)}}),[r,i]),t.createElement("div",{ref:a,style:e,className:n,key:JSON.stringify(r),...r,dangerouslySetInnerHTML:s?{__html:s}:void 0})},l=`#graphql\n\tfragment OkendoStarRatingSnippet on Product {\n\t\tokendoStarRatingSnippet: metafield(\n\t\t\tnamespace: "${s}--reviews"\n\t\t\tkey: "star_rating_snippet"\n\t\t) {\n\t\t\tvalue\n\t\t}\n\t}\n`,c=`#graphql\n\tfragment OkendoReviewsSnippet on Product {\n\t\tokendoReviewsSnippet: metafield(\n\t\t\tnamespace: "${s}--reviews"\n\t\t\tkey: "reviews_widget_snippet"\n\t\t) {\n\t\t\tvalue\n\t\t}\n\t}\n`;exports.OKENDO_PRODUCT_REVIEWS_FRAGMENT=c,exports.OKENDO_PRODUCT_STAR_RATING_FRAGMENT=l,exports.OkendoLoyaltyEmbeddedWidget=function(){const n=e.useLocation();return t.useEffect((()=>{window?.okeLoyaltyApi?.initialiseWidgets()}),[n.pathname]),t.createElement("div",{"data-oke-loyalty-embedded-widget":""})},exports.OkendoProvider=({okendoProviderData:r,customerAccessToken:s,productUrlFormatter:a,cdnDomain:o,children:d})=>t.createElement(t.Fragment,null,t.createElement(t.Suspense,null,t.createElement(e.Await,{resolve:r},(e=>t.createElement(i,{okendoProviderData:e,productUrlFormatter:a,cdnDomain:o})))),s&&t.createElement(n.Script,{id:"oke-loyalty-customer-access-token",type:"application/json",dangerouslySetInnerHTML:{__html:JSON.stringify({customerAccessToken:s})}}),d),exports.OkendoReviews=({style:e,className:n,productId:r,okendoReviewsSnippet:s})=>{const o=r?.length?a(r):null,i=r?.length?s:null,l={"data-oke-widget":"","data-oke-reviews-product-id":o};return t.createElement(d,{style:e,className:n,dataAttributes:l,metafieldContent:i?.value})},exports.OkendoReviewsCarousel=({style:e,className:n,productId:r,groupId:s,headerBadgeUrl:o})=>{const i={"data-oke-carousel":"","data-oke-reviews-product-id":r?.length?a(r):null,"data-oke-reviews-group-id":s?.length?s:null,"data-oke-header-badge-url":o};return t.createElement(d,{style:e,className:n,dataAttributes:i})},exports.OkendoStarRating=({style:e,className:n,productId:r,okendoStarRatingSnippet:s})=>{const o={"data-oke-star-rating":"","data-oke-reviews-product-id":a(r)};return t.createElement(d,{style:e,className:n,dataAttributes:o,metafieldContent:s?.value})},exports.getOkendoProviderData=async({context:e,subscriberId:t,apiDomain:n,okendoProducts:r=["reviews"],appNamespace:a})=>{if(!r.length)return null;const o=`loyaltySettings: metafield(\n namespace: "${a??s}--loyalty",\n key: "loyalty_settings"\n ) {\n value\n }`,i=`widgetPreRenderStyleTags: metafield(\n namespace: "${a??s}--reviews",\n key: "widget_pre_render_style_tags"\n ) {\n value\n }`,d=`#graphql\n query metafields {\n shop {\n ${r.includes("loyalty")?o:""}\n ${r.includes("reviews")?i:""}\n }\n }\n `,{shop:{loyaltySettings:l,widgetPreRenderStyleTags:c}}=await e.storefront.query(d);let u=null;if(r.includes("loyalty")&&(u={...u??{},loyaltySettings:l?.value??""}),r.includes("reviews")){const e=`https://${n||"api.okendo.io/v1"}/stores/${t}/widget_plus_settings`,r=await fetch(e);if(!r.ok)return console.error(`Failed to retrieve subscriber settings for subscriber ID '${t}'.`),u;const{reviewsHeaderConfig:s,cssVariables:a,customCss:o,starSymbols:i}=await r.json(),d=c?.value??"";d||console.warn("Failed to retrieve pre-rendered widget style settings."),u={...u??{},reviewsHeaderConfig:s,cssVariables:a,customCss:o,preRenderStyleTags:d,starSymbols:i}}return u};
1
+ "use strict";var e=require("react"),t=require("@shopify/hydrogen"),n=require("react-router");const r=/^[0-9]*$/,s="app--1576377";function o(e){if(e)return`shopify-${r.test(e)?e:e.split("/").slice(-1)[0]}`}const a="cdn-static.okendo.io",i=({okendoProviderData:n,productUrlFormatter:r,cdnDomain:s})=>{const o=e.useRef(!1),i=e.useRef(!1);if(e.useEffect((()=>{if(n&&n.loyaltySettings&&!1===o.current){const e=document.createElement("script");e.src=`https://${s||a}/loyalty/js/init-onsite.js`,document.head.appendChild(e);const t=document.createElement("script");t.type="application/json",t.id="oke-loyalty-settings";const r=n.loyaltySettings?n.loyaltySettings.replaceAll(/<\/?script.*?>/g,""):"";t.innerHTML=r,document.head.appendChild(t),o.current=!0}}),[n,s]),e.useEffect((()=>{if(n&&!i.current){const e=document.createElement("script");e.src=`https://${s||a}/reviews-widget-plus/js/okendo-reviews.js`,document.head.appendChild(e),i.current=!0}}),[n,s]),!n)return null;const{reviewsHeaderConfig:l,cssVariables:d,customCss:c,preRenderStyleTags:u,starSymbols:p}=n,m=(d??"").replace('<style id="oke-css-vars">',"").replace("</style>",""),y=c?c.replace('<style id="oke-reviews-custom-css">',"").replace("</style>",""):"";return e.createElement(e.Fragment,null,e.createElement(t.Script,{id:"oke-reviews-settings",type:"application/json",dangerouslySetInnerHTML:{__html:JSON.stringify(l)}}),e.createElement("style",{id:"oke-css-vars",dangerouslySetInnerHTML:{__html:m}}),y&&e.createElement("style",{id:"oke-reviews-custom-css",dangerouslySetInnerHTML:{__html:y}}),e.createElement(t.Script,{type:"text/javascript",dangerouslySetInnerHTML:{__html:`window.okeProductUrlFormatter = ${"function"==typeof r?r.toString():"string"==typeof r?r:"(product) =>\n product && product.productHandle\n ? \"/products/\" + product.productHandle + (product.variantId ? '?variantId=' + product.variantId : '')\n : undefined"}`}}),u&&e.createElement("div",{dangerouslySetInnerHTML:{__html:u}}),p&&e.createElement("div",{dangerouslySetInnerHTML:{__html:p}}))};const l=({style:t,className:n,dataAttributes:r,metafieldContent:s=""})=>{const o=e.useRef(null),a=e.useRef(!1),i=function(t){const n=e.useRef();return e.useEffect((()=>{n.current=t})),n.current}(r),l=()=>{o.current&&(window.okeWidgetApi.initWidget(o.current),a.current=!0)};return e.useEffect((()=>{if(!i||r["data-oke-widget"]!==i["data-oke-widget"]||r["data-oke-star-rating"]!==i["data-oke-star-rating"]||r["data-oke-reviews-product-id"]!==i["data-oke-reviews-product-id"]||!a.current)return window.okeWidgetApi&&o.current?l():document.addEventListener("oke-script-loaded",l),()=>{document.removeEventListener("oke-script-loaded",l)}}),[r,i]),e.createElement("div",{ref:o,style:t,className:n,key:JSON.stringify(r),...r,dangerouslySetInnerHTML:s?{__html:s}:void 0})},d=`#graphql\n\tfragment OkendoStarRatingSnippet on Product {\n\t\tokendoStarRatingSnippet: metafield(\n\t\t\tnamespace: "${s}--reviews"\n\t\t\tkey: "star_rating_snippet"\n\t\t) {\n\t\t\tvalue\n\t\t}\n\t}\n`,c=`#graphql\n\tfragment OkendoReviewsSnippet on Product {\n\t\tokendoReviewsSnippet: metafield(\n\t\t\tnamespace: "${s}--reviews"\n\t\t\tkey: "reviews_widget_snippet"\n\t\t) {\n\t\t\tvalue\n\t\t}\n\t}\n`;exports.OKENDO_PRODUCT_REVIEWS_FRAGMENT=c,exports.OKENDO_PRODUCT_STAR_RATING_FRAGMENT=d,exports.OkendoLoyaltyEmbeddedWidget=function(){return e.useEffect((()=>{window?.okeLoyaltyApi?.initialiseWidgets()}),[]),e.createElement("div",{"data-oke-loyalty-embedded-widget":""})},exports.OkendoProvider=({okendoProviderData:r,customerAccessToken:s,storefrontAccessToken:o,storefrontCustomerAccessToken:a,productUrlFormatter:l,cdnDomain:d,children:c})=>e.createElement(e.Fragment,null,e.createElement(e.Suspense,null,e.createElement(n.Await,{resolve:r},(t=>e.createElement(i,{okendoProviderData:t,productUrlFormatter:l,cdnDomain:d})))),s&&e.createElement(t.Script,{id:"oke-loyalty-customer-access-token",type:"application/json",dangerouslySetInnerHTML:{__html:JSON.stringify({customerAccessToken:s})}}),o&&a&&e.createElement(t.Script,{id:"oke-loyalty-storefront-customer-access-token",type:"application/json",dangerouslySetInnerHTML:{__html:JSON.stringify({storefrontAccessToken:o,storefrontCustomerAccessToken:a})}}),c),exports.OkendoReviews=({style:t,className:n,productId:r,okendoReviewsSnippet:s})=>{const a=r?.length?o(r):null,i=r?.length?s:null,d={"data-oke-widget":"","data-oke-reviews-product-id":a};return e.createElement(l,{style:t,className:n,dataAttributes:d,metafieldContent:i?.value})},exports.OkendoReviewsCarousel=({style:t,className:n,productId:r,groupId:s,headerBadgeUrl:a})=>{const i={"data-oke-carousel":"","data-oke-reviews-product-id":r?.length?o(r):null,"data-oke-reviews-group-id":s?.length?s:null,"data-oke-header-badge-url":a};return e.createElement(l,{style:t,className:n,dataAttributes:i})},exports.OkendoStarRating=({style:t,className:n,productId:r,okendoStarRatingSnippet:s})=>{const a={"data-oke-star-rating":"","data-oke-reviews-product-id":o(r)};return e.createElement(l,{style:t,className:n,dataAttributes:a,metafieldContent:s?.value})},exports.getOkendoProviderData=async({context:e,subscriberId:t,apiDomain:n,okendoProducts:r=["reviews"],appNamespace:o})=>{if(!r.length)return null;const a=`loyaltySettings: metafield(\n namespace: "${o??s}--loyalty",\n key: "loyalty_settings"\n ) {\n value\n }`,i=`widgetPreRenderStyleTags: metafield(\n namespace: "${o??s}--reviews",\n key: "widget_pre_render_style_tags"\n ) {\n value\n }`,l=`#graphql\n query metafields {\n shop {\n ${r.includes("loyalty")?a:""}\n ${r.includes("reviews")?i:""}\n }\n }\n `,{shop:{loyaltySettings:d,widgetPreRenderStyleTags:c}}=await e.storefront.query(l);let u=null;if(r.includes("loyalty")&&(u={...u??{},loyaltySettings:d?.value??""}),r.includes("reviews")){const e=`https://${n||"api.okendo.io/v1"}/stores/${t}/widget_plus_settings`,r=await fetch(e);if(!r.ok)return console.error(`Failed to retrieve subscriber settings for subscriber ID '${t}'.`),u;const{reviewsHeaderConfig:s,cssVariables:o,customCss:a,starSymbols:i}=await r.json(),l=c?.value??"";l||console.warn("Failed to retrieve pre-rendered widget style settings."),u={...u??{},reviewsHeaderConfig:s,cssVariables:o,customCss:a,preRenderStyleTags:l,starSymbols:i}}return u};
@@ -40,13 +40,25 @@ interface OkendoProviderProps {
40
40
  */
41
41
  okendoProviderData: Promise<OkendoProviderData | null>;
42
42
  /**
43
- * Used by the loyalty widget to verify the user's identity via the Storefront API.
43
+ * Used by the loyalty widget to verify the user's identity via the Customer Account API.
44
44
  * Can be retrieved via `await context.customerAccount.getAccessToken()` in the loader function.
45
45
  */
46
46
  customerAccessToken?: string;
47
+ /**
48
+ * As an alternative to `customerAccessToken` for stores which use the Storefront API for login
49
+ * Please use the value of the string: `customerAccessToken.accessToken` from the login response
50
+ * Caveat: This can only be used in tandem with your `storefrontAccessToken`
51
+ */
52
+ storefrontCustomerAccessToken?: string;
53
+ /**
54
+ * Required if you are using the Storefront API for login via the `storefrontCustomerAccessToken`
55
+ * Most likely in your project as `PUBLIC_STOREFRONT_API_TOKEN` and being used as the value of your `X-Shopify-Storefront-Access-Token` header
56
+ * Can also be found in the Shopify Admin, in the Headless Sales Channel settings as the Storefront API `Public access token`
57
+ */
58
+ storefrontAccessToken?: string;
47
59
  /** An optional product URL formatter */
48
60
  productUrlFormatter?: (product: ReviewProduct) => string;
49
61
  cdnDomain?: string;
50
62
  }
51
- export declare const OkendoProvider: ({ okendoProviderData, customerAccessToken, productUrlFormatter, cdnDomain, children, }: OkendoProviderProps & PropsWithChildren) => React.JSX.Element;
63
+ export declare const OkendoProvider: ({ okendoProviderData, customerAccessToken, storefrontAccessToken, storefrontCustomerAccessToken, productUrlFormatter, cdnDomain, children, }: OkendoProviderProps & PropsWithChildren) => React.JSX.Element;
52
64
  export {};
package/dist/esm/index.js CHANGED
@@ -1 +1 @@
1
- import{useLocation as e,Await as t}from"react-router";import n,{useEffect as r,Suspense as a,useRef as s}from"react";import{Script as o}from"@shopify/hydrogen";function i(){const t=e();return r((()=>{window?.okeLoyaltyApi?.initialiseWidgets()}),[t.pathname]),n.createElement("div",{"data-oke-loyalty-embedded-widget":""})}const l=/^[0-9]*$/,d="app--1576377";function c(e){if(e)return`shopify-${l.test(e)?e:e.split("/").slice(-1)[0]}`}const u="cdn-static.okendo.io",p=async({context:e,subscriberId:t,apiDomain:n,okendoProducts:r=["reviews"],appNamespace:a})=>{if(!r.length)return null;const s=`loyaltySettings: metafield(\n namespace: "${a??d}--loyalty",\n key: "loyalty_settings"\n ) {\n value\n }`,o=`widgetPreRenderStyleTags: metafield(\n namespace: "${a??d}--reviews",\n key: "widget_pre_render_style_tags"\n ) {\n value\n }`,i=`#graphql\n query metafields {\n shop {\n ${r.includes("loyalty")?s:""}\n ${r.includes("reviews")?o:""}\n }\n }\n `,{shop:{loyaltySettings:l,widgetPreRenderStyleTags:c}}=await e.storefront.query(i);let u=null;if(r.includes("loyalty")&&(u={...u??{},loyaltySettings:l?.value??""}),r.includes("reviews")){const e=`https://${n||"api.okendo.io/v1"}/stores/${t}/widget_plus_settings`,r=await fetch(e);if(!r.ok)return console.error(`Failed to retrieve subscriber settings for subscriber ID '${t}'.`),u;const{reviewsHeaderConfig:a,cssVariables:s,customCss:o,starSymbols:i}=await r.json(),l=c?.value??"";l||console.warn("Failed to retrieve pre-rendered widget style settings."),u={...u??{},reviewsHeaderConfig:a,cssVariables:s,customCss:o,preRenderStyleTags:l,starSymbols:i}}return u},m=({okendoProviderData:e,customerAccessToken:r,productUrlFormatter:s,cdnDomain:i,children:l})=>n.createElement(n.Fragment,null,n.createElement(a,null,n.createElement(t,{resolve:e},(e=>n.createElement(y,{okendoProviderData:e,productUrlFormatter:s,cdnDomain:i})))),r&&n.createElement(o,{id:"oke-loyalty-customer-access-token",type:"application/json",dangerouslySetInnerHTML:{__html:JSON.stringify({customerAccessToken:r})}}),l),y=({okendoProviderData:e,productUrlFormatter:t,cdnDomain:a})=>{const i=s(!1),l=s(!1);if(r((()=>{if(e&&e.loyaltySettings&&!1===i.current){const t=document.createElement("script");t.src=`https://${a||u}/loyalty/js/init-onsite.js`,document.head.appendChild(t);const n=document.createElement("script");n.type="application/json",n.id="oke-loyalty-settings";const r=e.loyaltySettings?e.loyaltySettings.replaceAll(/<\/?script.*?>/g,""):"";n.innerHTML=r,document.head.appendChild(n),i.current=!0}}),[e,a]),r((()=>{if(e&&!l.current){const e=document.createElement("script");e.src=`https://${a||u}/reviews-widget-plus/js/okendo-reviews.js`,document.head.appendChild(e),l.current=!0}}),[e,a]),!e)return null;const{reviewsHeaderConfig:d,cssVariables:c,customCss:p,preRenderStyleTags:m,starSymbols:y}=e,g=(c??"").replace('<style id="oke-css-vars">',"").replace("</style>",""),v=p?p.replace('<style id="oke-reviews-custom-css">',"").replace("</style>",""):"";return n.createElement(n.Fragment,null,n.createElement(o,{id:"oke-reviews-settings",type:"application/json",dangerouslySetInnerHTML:{__html:JSON.stringify(d)}}),n.createElement("style",{id:"oke-css-vars",dangerouslySetInnerHTML:{__html:g}}),v&&n.createElement("style",{id:"oke-reviews-custom-css",dangerouslySetInnerHTML:{__html:v}}),n.createElement(o,{type:"text/javascript",dangerouslySetInnerHTML:{__html:`window.okeProductUrlFormatter = ${"function"==typeof t?t.toString():"string"==typeof t?t:"(product) =>\n product && product.productHandle\n ? \"/products/\" + product.productHandle + (product.variantId ? '?variantId=' + product.variantId : '')\n : undefined"}`}}),m&&n.createElement("div",{dangerouslySetInnerHTML:{__html:m}}),y&&n.createElement("div",{dangerouslySetInnerHTML:{__html:y}}))};const g=({style:e,className:t,dataAttributes:a,metafieldContent:o=""})=>{const i=s(null),l=s(!1),d=function(e){const t=s();return r((()=>{t.current=e})),t.current}(a),c=()=>{i.current&&(window.okeWidgetApi.initWidget(i.current),l.current=!0)};return r((()=>{if(!d||a["data-oke-widget"]!==d["data-oke-widget"]||a["data-oke-star-rating"]!==d["data-oke-star-rating"]||a["data-oke-reviews-product-id"]!==d["data-oke-reviews-product-id"]||!l.current)return window.okeWidgetApi&&i.current?c():document.addEventListener("oke-script-loaded",c),()=>{document.removeEventListener("oke-script-loaded",c)}}),[a,d]),n.createElement("div",{ref:i,style:e,className:t,key:JSON.stringify(a),...a,dangerouslySetInnerHTML:o?{__html:o}:void 0})},v=({style:e,className:t,productId:r,okendoReviewsSnippet:a})=>{const s=r?.length?c(r):null,o=r?.length?a:null,i={"data-oke-widget":"","data-oke-reviews-product-id":s};return n.createElement(g,{style:e,className:t,dataAttributes:i,metafieldContent:o?.value})},k=({style:e,className:t,productId:r,groupId:a,headerBadgeUrl:s})=>{const o={"data-oke-carousel":"","data-oke-reviews-product-id":r?.length?c(r):null,"data-oke-reviews-group-id":a?.length?a:null,"data-oke-header-badge-url":s};return n.createElement(g,{style:e,className:t,dataAttributes:o})},w=({style:e,className:t,productId:r,okendoStarRatingSnippet:a})=>{const s={"data-oke-star-rating":"","data-oke-reviews-product-id":c(r)};return n.createElement(g,{style:e,className:t,dataAttributes:s,metafieldContent:a?.value})},f=`#graphql\n\tfragment OkendoStarRatingSnippet on Product {\n\t\tokendoStarRatingSnippet: metafield(\n\t\t\tnamespace: "${d}--reviews"\n\t\t\tkey: "star_rating_snippet"\n\t\t) {\n\t\t\tvalue\n\t\t}\n\t}\n`,h=`#graphql\n\tfragment OkendoReviewsSnippet on Product {\n\t\tokendoReviewsSnippet: metafield(\n\t\t\tnamespace: "${d}--reviews"\n\t\t\tkey: "reviews_widget_snippet"\n\t\t) {\n\t\t\tvalue\n\t\t}\n\t}\n`;export{h as OKENDO_PRODUCT_REVIEWS_FRAGMENT,f as OKENDO_PRODUCT_STAR_RATING_FRAGMENT,i as OkendoLoyaltyEmbeddedWidget,m as OkendoProvider,v as OkendoReviews,k as OkendoReviewsCarousel,w as OkendoStarRating,p as getOkendoProviderData};
1
+ import e,{useEffect as t,Suspense as n,useRef as r}from"react";import{Script as s}from"@shopify/hydrogen";import{Await as a}from"react-router";function o(){return t((()=>{window?.okeLoyaltyApi?.initialiseWidgets()}),[]),e.createElement("div",{"data-oke-loyalty-embedded-widget":""})}const i=/^[0-9]*$/,l="app--1576377";function d(e){if(e)return`shopify-${i.test(e)?e:e.split("/").slice(-1)[0]}`}const c="cdn-static.okendo.io",u=async({context:e,subscriberId:t,apiDomain:n,okendoProducts:r=["reviews"],appNamespace:s})=>{if(!r.length)return null;const a=`loyaltySettings: metafield(\n namespace: "${s??l}--loyalty",\n key: "loyalty_settings"\n ) {\n value\n }`,o=`widgetPreRenderStyleTags: metafield(\n namespace: "${s??l}--reviews",\n key: "widget_pre_render_style_tags"\n ) {\n value\n }`,i=`#graphql\n query metafields {\n shop {\n ${r.includes("loyalty")?a:""}\n ${r.includes("reviews")?o:""}\n }\n }\n `,{shop:{loyaltySettings:d,widgetPreRenderStyleTags:c}}=await e.storefront.query(i);let u=null;if(r.includes("loyalty")&&(u={...u??{},loyaltySettings:d?.value??""}),r.includes("reviews")){const e=`https://${n||"api.okendo.io/v1"}/stores/${t}/widget_plus_settings`,r=await fetch(e);if(!r.ok)return console.error(`Failed to retrieve subscriber settings for subscriber ID '${t}'.`),u;const{reviewsHeaderConfig:s,cssVariables:a,customCss:o,starSymbols:i}=await r.json(),l=c?.value??"";l||console.warn("Failed to retrieve pre-rendered widget style settings."),u={...u??{},reviewsHeaderConfig:s,cssVariables:a,customCss:o,preRenderStyleTags:l,starSymbols:i}}return u},p=({okendoProviderData:t,customerAccessToken:r,storefrontAccessToken:o,storefrontCustomerAccessToken:i,productUrlFormatter:l,cdnDomain:d,children:c})=>e.createElement(e.Fragment,null,e.createElement(n,null,e.createElement(a,{resolve:t},(t=>e.createElement(m,{okendoProviderData:t,productUrlFormatter:l,cdnDomain:d})))),r&&e.createElement(s,{id:"oke-loyalty-customer-access-token",type:"application/json",dangerouslySetInnerHTML:{__html:JSON.stringify({customerAccessToken:r})}}),o&&i&&e.createElement(s,{id:"oke-loyalty-storefront-customer-access-token",type:"application/json",dangerouslySetInnerHTML:{__html:JSON.stringify({storefrontAccessToken:o,storefrontCustomerAccessToken:i})}}),c),m=({okendoProviderData:n,productUrlFormatter:a,cdnDomain:o})=>{const i=r(!1),l=r(!1);if(t((()=>{if(n&&n.loyaltySettings&&!1===i.current){const e=document.createElement("script");e.src=`https://${o||c}/loyalty/js/init-onsite.js`,document.head.appendChild(e);const t=document.createElement("script");t.type="application/json",t.id="oke-loyalty-settings";const r=n.loyaltySettings?n.loyaltySettings.replaceAll(/<\/?script.*?>/g,""):"";t.innerHTML=r,document.head.appendChild(t),i.current=!0}}),[n,o]),t((()=>{if(n&&!l.current){const e=document.createElement("script");e.src=`https://${o||c}/reviews-widget-plus/js/okendo-reviews.js`,document.head.appendChild(e),l.current=!0}}),[n,o]),!n)return null;const{reviewsHeaderConfig:d,cssVariables:u,customCss:p,preRenderStyleTags:m,starSymbols:y}=n,g=(u??"").replace('<style id="oke-css-vars">',"").replace("</style>",""),k=p?p.replace('<style id="oke-reviews-custom-css">',"").replace("</style>",""):"";return e.createElement(e.Fragment,null,e.createElement(s,{id:"oke-reviews-settings",type:"application/json",dangerouslySetInnerHTML:{__html:JSON.stringify(d)}}),e.createElement("style",{id:"oke-css-vars",dangerouslySetInnerHTML:{__html:g}}),k&&e.createElement("style",{id:"oke-reviews-custom-css",dangerouslySetInnerHTML:{__html:k}}),e.createElement(s,{type:"text/javascript",dangerouslySetInnerHTML:{__html:`window.okeProductUrlFormatter = ${"function"==typeof a?a.toString():"string"==typeof a?a:"(product) =>\n product && product.productHandle\n ? \"/products/\" + product.productHandle + (product.variantId ? '?variantId=' + product.variantId : '')\n : undefined"}`}}),m&&e.createElement("div",{dangerouslySetInnerHTML:{__html:m}}),y&&e.createElement("div",{dangerouslySetInnerHTML:{__html:y}}))};const y=({style:n,className:s,dataAttributes:a,metafieldContent:o=""})=>{const i=r(null),l=r(!1),d=function(e){const n=r();return t((()=>{n.current=e})),n.current}(a),c=()=>{i.current&&(window.okeWidgetApi.initWidget(i.current),l.current=!0)};return t((()=>{if(!d||a["data-oke-widget"]!==d["data-oke-widget"]||a["data-oke-star-rating"]!==d["data-oke-star-rating"]||a["data-oke-reviews-product-id"]!==d["data-oke-reviews-product-id"]||!l.current)return window.okeWidgetApi&&i.current?c():document.addEventListener("oke-script-loaded",c),()=>{document.removeEventListener("oke-script-loaded",c)}}),[a,d]),e.createElement("div",{ref:i,style:n,className:s,key:JSON.stringify(a),...a,dangerouslySetInnerHTML:o?{__html:o}:void 0})},g=({style:t,className:n,productId:r,okendoReviewsSnippet:s})=>{const a=r?.length?d(r):null,o=r?.length?s:null,i={"data-oke-widget":"","data-oke-reviews-product-id":a};return e.createElement(y,{style:t,className:n,dataAttributes:i,metafieldContent:o?.value})},k=({style:t,className:n,productId:r,groupId:s,headerBadgeUrl:a})=>{const o={"data-oke-carousel":"","data-oke-reviews-product-id":r?.length?d(r):null,"data-oke-reviews-group-id":s?.length?s:null,"data-oke-header-badge-url":a};return e.createElement(y,{style:t,className:n,dataAttributes:o})},v=({style:t,className:n,productId:r,okendoStarRatingSnippet:s})=>{const a={"data-oke-star-rating":"","data-oke-reviews-product-id":d(r)};return e.createElement(y,{style:t,className:n,dataAttributes:a,metafieldContent:s?.value})},w=`#graphql\n\tfragment OkendoStarRatingSnippet on Product {\n\t\tokendoStarRatingSnippet: metafield(\n\t\t\tnamespace: "${l}--reviews"\n\t\t\tkey: "star_rating_snippet"\n\t\t) {\n\t\t\tvalue\n\t\t}\n\t}\n`,f=`#graphql\n\tfragment OkendoReviewsSnippet on Product {\n\t\tokendoReviewsSnippet: metafield(\n\t\t\tnamespace: "${l}--reviews"\n\t\t\tkey: "reviews_widget_snippet"\n\t\t) {\n\t\t\tvalue\n\t\t}\n\t}\n`;export{f as OKENDO_PRODUCT_REVIEWS_FRAGMENT,w as OKENDO_PRODUCT_STAR_RATING_FRAGMENT,o as OkendoLoyaltyEmbeddedWidget,p as OkendoProvider,g as OkendoReviews,k as OkendoReviewsCarousel,v as OkendoStarRating,u as getOkendoProviderData};
@@ -40,13 +40,25 @@ interface OkendoProviderProps {
40
40
  */
41
41
  okendoProviderData: Promise<OkendoProviderData | null>;
42
42
  /**
43
- * Used by the loyalty widget to verify the user's identity via the Storefront API.
43
+ * Used by the loyalty widget to verify the user's identity via the Customer Account API.
44
44
  * Can be retrieved via `await context.customerAccount.getAccessToken()` in the loader function.
45
45
  */
46
46
  customerAccessToken?: string;
47
+ /**
48
+ * As an alternative to `customerAccessToken` for stores which use the Storefront API for login
49
+ * Please use the value of the string: `customerAccessToken.accessToken` from the login response
50
+ * Caveat: This can only be used in tandem with your `storefrontAccessToken`
51
+ */
52
+ storefrontCustomerAccessToken?: string;
53
+ /**
54
+ * Required if you are using the Storefront API for login via the `storefrontCustomerAccessToken`
55
+ * Most likely in your project as `PUBLIC_STOREFRONT_API_TOKEN` and being used as the value of your `X-Shopify-Storefront-Access-Token` header
56
+ * Can also be found in the Shopify Admin, in the Headless Sales Channel settings as the Storefront API `Public access token`
57
+ */
58
+ storefrontAccessToken?: string;
47
59
  /** An optional product URL formatter */
48
60
  productUrlFormatter?: (product: ReviewProduct) => string;
49
61
  cdnDomain?: string;
50
62
  }
51
- export declare const OkendoProvider: ({ okendoProviderData, customerAccessToken, productUrlFormatter, cdnDomain, children, }: OkendoProviderProps & PropsWithChildren) => React.JSX.Element;
63
+ export declare const OkendoProvider: ({ okendoProviderData, customerAccessToken, storefrontAccessToken, storefrontCustomerAccessToken, productUrlFormatter, cdnDomain, children, }: OkendoProviderProps & PropsWithChildren) => React.JSX.Element;
52
64
  export {};
package/dist/index.d.ts CHANGED
@@ -50,15 +50,27 @@ interface OkendoProviderProps {
50
50
  */
51
51
  okendoProviderData: Promise<OkendoProviderData | null>;
52
52
  /**
53
- * Used by the loyalty widget to verify the user's identity via the Storefront API.
53
+ * Used by the loyalty widget to verify the user's identity via the Customer Account API.
54
54
  * Can be retrieved via `await context.customerAccount.getAccessToken()` in the loader function.
55
55
  */
56
56
  customerAccessToken?: string;
57
+ /**
58
+ * As an alternative to `customerAccessToken` for stores which use the Storefront API for login
59
+ * Please use the value of the string: `customerAccessToken.accessToken` from the login response
60
+ * Caveat: This can only be used in tandem with your `storefrontAccessToken`
61
+ */
62
+ storefrontCustomerAccessToken?: string;
63
+ /**
64
+ * Required if you are using the Storefront API for login via the `storefrontCustomerAccessToken`
65
+ * Most likely in your project as `PUBLIC_STOREFRONT_API_TOKEN` and being used as the value of your `X-Shopify-Storefront-Access-Token` header
66
+ * Can also be found in the Shopify Admin, in the Headless Sales Channel settings as the Storefront API `Public access token`
67
+ */
68
+ storefrontAccessToken?: string;
57
69
  /** An optional product URL formatter */
58
70
  productUrlFormatter?: (product: ReviewProduct) => string;
59
71
  cdnDomain?: string;
60
72
  }
61
- declare const OkendoProvider: ({ okendoProviderData, customerAccessToken, productUrlFormatter, cdnDomain, children, }: OkendoProviderProps & PropsWithChildren) => React.JSX.Element;
73
+ declare const OkendoProvider: ({ okendoProviderData, customerAccessToken, storefrontAccessToken, storefrontCustomerAccessToken, productUrlFormatter, cdnDomain, children, }: OkendoProviderProps & PropsWithChildren) => React.JSX.Element;
62
74
 
63
75
  interface MetafieldValue {
64
76
  value: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@okendo/shopify-hydrogen",
3
- "version": "2.6.1",
3
+ "version": "2.6.2",
4
4
  "description": "Okendo React components for Shopify Hydrogen",
5
5
  "author": "Okendo",
6
6
  "license": "SEE LICENSE IN LICENSE.txt",