@okendo/shopify-hydrogen 1.3.0 → 2.0.0

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.
Files changed (76) hide show
  1. package/LICENSE.txt +1 -1
  2. package/README.md +376 -464
  3. package/dist/cjs/index.js +1 -0
  4. package/dist/cjs/types/components/OkendoProvider/OkendoProvider.d.ts +36 -0
  5. package/dist/cjs/types/components/OkendoProvider/index.d.ts +1 -0
  6. package/dist/cjs/types/components/OkendoReviews/OkendoReviews.d.ts +11 -0
  7. package/dist/cjs/types/components/OkendoReviews/index.d.ts +1 -0
  8. package/dist/cjs/types/components/OkendoStarRating/OkendoStarRating.d.ts +11 -0
  9. package/dist/cjs/types/components/OkendoStarRating/index.d.ts +1 -0
  10. package/dist/cjs/types/components/index.d.ts +3 -0
  11. package/dist/cjs/types/fragments/fragments.d.ts +2 -0
  12. package/dist/cjs/types/fragments/index.d.ts +1 -0
  13. package/dist/cjs/types/index.d.ts +2 -0
  14. package/dist/cjs/types/internal/OkendoWidget/OkendoWidget.d.ts +12 -0
  15. package/dist/cjs/types/internal/types.d.ts +3 -0
  16. package/dist/esm/index.js +1 -0
  17. package/dist/esm/types/components/OkendoProvider/OkendoProvider.d.ts +36 -0
  18. package/dist/esm/types/components/OkendoProvider/index.d.ts +1 -0
  19. package/dist/esm/types/components/OkendoReviews/OkendoReviews.d.ts +11 -0
  20. package/dist/esm/types/components/OkendoReviews/index.d.ts +1 -0
  21. package/dist/esm/types/components/OkendoStarRating/OkendoStarRating.d.ts +11 -0
  22. package/dist/esm/types/components/OkendoStarRating/index.d.ts +1 -0
  23. package/dist/esm/types/components/index.d.ts +3 -0
  24. package/dist/esm/types/fragments/fragments.d.ts +2 -0
  25. package/dist/esm/types/fragments/index.d.ts +1 -0
  26. package/dist/esm/types/index.d.ts +2 -0
  27. package/dist/esm/types/internal/OkendoWidget/OkendoWidget.d.ts +12 -0
  28. package/dist/esm/types/internal/types.d.ts +3 -0
  29. package/dist/esm/types/internal/utils.d.ts +6 -0
  30. package/dist/index.d.ts +64 -0
  31. package/package.json +46 -63
  32. package/dist/esnext/client-components/OkendoClientStarRating.client.d.ts +0 -4
  33. package/dist/esnext/client-components/OkendoClientStarRating.client.js +0 -24
  34. package/dist/esnext/client-components/OkendoWidget.client.d.ts +0 -13
  35. package/dist/esnext/client-components/OkendoWidget.client.js +0 -23
  36. package/dist/esnext/client-components/index.d.ts +0 -1
  37. package/dist/esnext/client-components/index.js +0 -1
  38. package/dist/esnext/client.d.ts +0 -1
  39. package/dist/esnext/client.js +0 -1
  40. package/dist/esnext/components/OkendoProvider.server.d.ts +0 -15
  41. package/dist/esnext/components/OkendoProvider.server.js +0 -69
  42. package/dist/esnext/components/OkendoReviewsWidget.server.d.ts +0 -6
  43. package/dist/esnext/components/OkendoReviewsWidget.server.js +0 -61
  44. package/dist/esnext/components/OkendoStarRating.server.d.ts +0 -4
  45. package/dist/esnext/components/OkendoStarRating.server.js +0 -46
  46. package/dist/esnext/components/index.d.ts +0 -3
  47. package/dist/esnext/components/index.js +0 -3
  48. package/dist/esnext/fragments/index.d.ts +0 -1
  49. package/dist/esnext/fragments/index.js +0 -11
  50. package/dist/esnext/framework/index.d.ts +0 -0
  51. package/dist/esnext/framework/index.js +0 -1
  52. package/dist/esnext/framework/plugins/plugin.d.ts +0 -7
  53. package/dist/esnext/framework/plugins/plugin.js +0 -7
  54. package/dist/esnext/framework/plugins/suppressModuleWarning.d.ts +0 -3
  55. package/dist/esnext/framework/plugins/suppressModuleWarning.js +0 -18
  56. package/dist/esnext/index.d.ts +0 -4
  57. package/dist/esnext/index.js +0 -4
  58. package/dist/esnext/models/starRating.d.ts +0 -12
  59. package/dist/esnext/models/starRating.js +0 -1
  60. package/dist/esnext/shared/errorUtils.d.ts +0 -3
  61. package/dist/esnext/shared/errorUtils.js +0 -9
  62. package/dist/esnext/shared/logger.d.ts +0 -14
  63. package/dist/esnext/shared/logger.js +0 -7
  64. package/dist/esnext/shared/productUtils.js +0 -15
  65. package/dist/esnext/shared/server/requestUtils.d.ts +0 -7
  66. package/dist/esnext/shared/server/requestUtils.js +0 -4
  67. package/dist/esnext/shared/sharedTypes.d.ts +0 -5
  68. package/dist/esnext/shared/sharedTypes.js +0 -1
  69. package/dist/node/framework/index.d.ts +0 -0
  70. package/dist/node/framework/index.js +0 -1
  71. package/dist/node/framework/plugins/plugin.d.ts +0 -4
  72. package/dist/node/framework/plugins/plugin.js +0 -12
  73. package/dist/node/framework/plugins/suppressModuleWarning.d.ts +0 -3
  74. package/dist/node/framework/plugins/suppressModuleWarning.js +0 -20
  75. package/plugin.cjs +0 -1
  76. /package/dist/{esnext/shared/productUtils.d.ts → cjs/types/internal/utils.d.ts} +0 -0
package/README.md CHANGED
@@ -1,91 +1,48 @@
1
- # Okendo Hydrogen React Components
1
+ > Note: this package is to be used on stores built with Hydrogen v2, based on Remix. If your store is built with the now deprecated Hydrogen v1, please use [version 1 of this package](https://www.npmjs.com/package/@okendo/shopify-hydrogen/v/1.3.0).
2
2
 
3
- This is the React component library to support Okendo Widget Plus Widgets in Shopify Hydrogen Projects.
3
+ # Okendo Hydrogen 2 (Remix) React Components
4
4
 
5
- Currently we provide the following components:
6
-
7
- ### Server Components
8
-
9
- 1. [Reviews List](#components--okendo-reviews-widget)
10
- 2. [Star Ratings](#components--okendo-star-rating)
11
-
12
- ### Client Components
13
-
14
- 1. [Star Ratings](#components--okendo-client-star-rating)
15
-
16
- <br/>
17
-
18
- # Table of contents
19
-
20
- 1. [What is Okendo Shopify Hydrogen](#introduction)
21
- 2. [Guided Installation](#installation)
22
- - [Configure Hydrogen App](#configure-hydrogen-app-config)
23
- - [Expose Shopify Metafields](#expose-shopify-metafields)
24
- 3. [How to Use Okendo Hydrogen Components In Your Hydrogen Apps](#how-to-use-okendo-hydrogen-components-in-your-hydrogen-app)
25
- 4. [Components](#components)
26
- 5. [GraphQL Fragments](#graphql-fragments)
27
- 6. [View Our Okendo Sample Hydrogen App](#view-our-okendo-sample-hydrogen-app)
28
-
29
- <br/><br/>
30
-
31
- # What is Okendo Shopify Hydrogen? <a id="introduction" name="introduction"></a>
32
-
33
- Okendo Shopify Hydrogen is a React component library to be used in Shopify Hydrogen apps. This utilises [Shopify’s Hydrogen framework](https://shopify.dev/custom-storefronts/hydrogen/framework) which is used to create custom storefronts using both server-side rendered and client-side rendered React components.
34
-
35
- The purpose of this library is for a Hydrogen-based React Shopify storefront to import this library so that the Okendo Reviews List and Okendo Star Ratings components can be rendered within their React application, providing [Okendo’s reviews display functionality](https://www.okendo.io/blog/widget-plus/).
36
-
37
- <br/>
38
-
39
- # Guided Installation <a id="installation" name="installation"></a>
40
-
41
- The purpose of this documentation is to guide you on the following:
42
-
43
- - How to configure your Shopify store ready for Okendo Shopify Hydrogen.
44
- - How to install and configure Okendo Shopify Hydrogen components in your Shopify Hydrogen app.
45
-
46
- <br/>
5
+ This package brings [Okendo's review widgets](https://www.okendo.io/blog/widget-plus/) to a Shopify Hydrogen store.
47
6
 
48
7
  ## Requirements
49
8
 
50
- - You have an existing Shopify store.
51
- - You have an existing Hydrogen app. ([Learn how to create a Hydrogen app](https://shopify.dev/custom-storefronts/hydrogen/getting-started/create))
52
- - You have a current Okendo Reviews subscription and have the **Okendo: Product Reviews & UCG** app installed and configured.
53
- - You have an existing Shopify custom app with Storefront access token. ([Learn how to configure Shopify Storefront](https://github.com/okendo/okendo-shopify-hydrogen-demo/wiki/Configure-Shopify-Storefront-API))
9
+ - A Shopify store with the **Okendo: Product Reviews & UCG** app installed and configured.
10
+ - A current Okendo subscription.
11
+ - A [Storefront access token](https://github.com/okendo/okendo-shopify-hydrogen-demo/wiki/Configure-Shopify-Storefront-API).
12
+ - A [Shopify Hydrogen](https://hydrogen.shopify.dev/) app.
54
13
 
55
- <br/>
14
+ ## Demo Store
56
15
 
57
- ## Configure Hydrogen app config <a id="configure-hydrogen-app-config" name="configure-hydrogen-app-config"></a>
16
+ Our demo store, which is based on the demo store provided by Shopify, can be found [here](https://github.com/okendo/okendo-shopify-hydrogen-demo).
58
17
 
59
- 1. Open **hydrogen.config.ts** in your project.
60
- 2. Make the following changes and save the file:
61
- - Update `storeDomain` to specify your store's domain name.
62
- - Update `storefrontToken` to specify your Storefront API access token.
18
+ ## How it works
63
19
 
64
- <br/>
20
+ This package provides:
65
21
 
66
- ## Expose Shopify Metafields <a id="expose-shopify-metafields" name="expose-shopify-metafields"></a>
22
+ - one function: `getOkendoProviderData`
23
+ - three React components: `OkendoProvider`, `OkendoStarRating`, and `OkendoReviews`
67
24
 
68
- Okendo Reviews utilise Product and Shop specific [metafields](https://shopify.dev/api/examples/metafields) in order to function and provide a seamless user experience. You will need to expose these metafields so that they can be retrieved by your Hydrogen app.
25
+ The function `getOkendoProviderData` needs to be called in the `loader` function of the `root.tsx` file in the Hydrogen 2 store. The data is then retrieved in `App` through `useLoaderData` and provided to `OkendoProvider` which is added in the `body` of the HTML returned by `App`.
69
26
 
70
- At this point in time, unfortunately Shopify does not have a way of exposing Shop Metafields through their admin UI.
27
+ Then the components `OkendoStarRating` and `OkendoReviews` can be added on the store pages. There are a few more bits of configuration to do, please see below.
71
28
 
72
- The preferred method to expose Metafields is to [contact Okendo Support](mailto:support@okendo.io).
29
+ ## Expose Shopify Metafields <a id="expose-shopify-metafields" name="expose-shopify-metafields"></a>
73
30
 
74
- <br/>
31
+ Okendo Reviews use Product and Shop [metafields](https://shopify.dev/api/examples/metafields). You will need to expose these metafields so that they can be retrieved by your Hydrogen app.
75
32
 
76
- ### For Technical/Advanced Users
33
+ At the moment, Shopify does not have a way of exposing Shop Metafields through their admin UI, so the preferred method is to [contact Okendo Support](mailto:support@okendo.io).
77
34
 
78
35
  <details>
79
- <summary>Learn How to Expose Metafields Via The Storefront API</summary>
36
+ <summary>For technical users, follow this method to expose metafields via the storefront API</summary>
80
37
 
81
- ## Exposing Metafields via GraphQL
38
+ ### Exposing Metafields via GraphQL
82
39
 
83
- ### Using Curl
40
+ #### Using Curl
84
41
 
85
- You can also expose the required Okendo Shopify Metafields by using GraphQL with curl.
42
+ You can also expose the required Okendo Shopify metafields by using GraphQL with curl.
86
43
 
87
44
  1. Open a new terminal or PowerShell window.
88
- 2. Run the following command to expose the `WidgetPreRenderStyleTag` Shop Metafield.
45
+ 2. Run the following command to expose the `WidgetPreRenderStyleTags` shop metafield:
89
46
 
90
47
  ```bash
91
48
  curl -X POST \
@@ -94,26 +51,26 @@ https://{shop}.myshopify.com/admin/api/2022-04/graphql.json \
94
51
  -H 'X-Shopify-Access-Token: {access_token}' \
95
52
  -d '
96
53
  mutation {
97
- metafieldStorefrontVisibilityCreate(
98
- input: {
99
- namespace: "okendo"
100
- key: "WidgetPreRenderStyleTags"
101
- ownerType: SHOP
102
- }
103
- ) {
104
- metafieldStorefrontVisibility {
105
- id
106
- }
107
- userErrors {
108
- field
109
- message
110
- }
111
- }
54
+ metafieldStorefrontVisibilityCreate(
55
+ input: {
56
+ namespace: "okendo"
57
+ key: "WidgetPreRenderStyleTags"
58
+ ownerType: SHOP
59
+ }
60
+ ) {
61
+ metafieldStorefrontVisibility {
62
+ id
63
+ }
64
+ userErrors {
65
+ field
66
+ message
67
+ }
68
+ }
112
69
  }
113
70
  '
114
71
  ```
115
72
 
116
- 3. Run the following command to expose the `WidgetPreRenderBodyStyleTags` Shop Metafield.
73
+ 3. Run the following command to expose the `WidgetPreRenderBodyStyleTags` shop metafield:
117
74
 
118
75
  ```bash
119
76
  curl -X POST \
@@ -122,26 +79,26 @@ https://{shop}.myshopify.com/admin/api/2022-04/graphql.json \
122
79
  -H 'X-Shopify-Access-Token: {access_token}' \
123
80
  -d '
124
81
  mutation {
125
- metafieldStorefrontVisibilityCreate(
126
- input: {
127
- namespace: "okendo"
128
- key: "WidgetPreRenderBodyStyleTags"
129
- ownerType: SHOP
130
- }
131
- ) {
132
- metafieldStorefrontVisibility {
133
- id
134
- }
135
- userErrors {
136
- field
137
- message
138
- }
139
- }
82
+ metafieldStorefrontVisibilityCreate(
83
+ input: {
84
+ namespace: "okendo"
85
+ key: "WidgetPreRenderBodyStyleTags"
86
+ ownerType: SHOP
87
+ }
88
+ ) {
89
+ metafieldStorefrontVisibility {
90
+ id
91
+ }
92
+ userErrors {
93
+ field
94
+ message
95
+ }
96
+ }
140
97
  }
141
98
  '
142
99
  ```
143
100
 
144
- 4. Run the following command to expose the `ReviewsWidgetSnippet` Product Metafield.
101
+ 4. Run the following command to expose the `ReviewsWidgetSnippet` product metafield:
145
102
 
146
103
  ```bash
147
104
  curl -X POST \
@@ -150,26 +107,26 @@ https://{shop}.myshopify.com/admin/api/2022-04/graphql.json \
150
107
  -H 'X-Shopify-Access-Token: {access_token}' \
151
108
  -d '
152
109
  mutation {
153
- metafieldStorefrontVisibilityCreate(
154
- input: {
155
- namespace: "okendo"
156
- key: "ReviewsWidgetSnippet"
157
- ownerType: PRODUCT
158
- }
159
- ) {
160
- metafieldStorefrontVisibility {
161
- id
162
- }
163
- userErrors {
164
- field
165
- message
166
- }
167
- }
110
+ metafieldStorefrontVisibilityCreate(
111
+ input: {
112
+ namespace: "okendo"
113
+ key: "ReviewsWidgetSnippet"
114
+ ownerType: PRODUCT
115
+ }
116
+ ) {
117
+ metafieldStorefrontVisibility {
118
+ id
119
+ }
120
+ userErrors {
121
+ field
122
+ message
123
+ }
124
+ }
168
125
  }
169
126
  '
170
127
  ```
171
128
 
172
- 5. Run the following command to expose the `StarRatingSnippet` the Product Metafield.
129
+ 5. Run the following command to expose the `StarRatingSnippet` the product metafield:
173
130
 
174
131
  ```bash
175
132
  curl -X POST \
@@ -178,21 +135,21 @@ https://{shop}.myshopify.com/admin/api/2022-04/graphql.json \
178
135
  -H 'X-Shopify-Access-Token: {access_token}' \
179
136
  -d '
180
137
  mutation {
181
- metafieldStorefrontVisibilityCreate(
182
- input: {
183
- namespace: "okendo"
184
- key: "StarRatingSnippet"
185
- ownerType: PRODUCT
186
- }
187
- ) {
188
- metafieldStorefrontVisibility {
189
- id
190
- }
191
- userErrors {
192
- field
193
- message
194
- }
195
- }
138
+ metafieldStorefrontVisibilityCreate(
139
+ input: {
140
+ namespace: "okendo"
141
+ key: "StarRatingSnippet"
142
+ ownerType: PRODUCT
143
+ }
144
+ ) {
145
+ metafieldStorefrontVisibility {
146
+ id
147
+ }
148
+ userErrors {
149
+ field
150
+ message
151
+ }
152
+ }
196
153
  }
197
154
  '
198
155
  ```
@@ -200,89 +157,91 @@ mutation {
200
157
  ### Using GraphQL IDE
201
158
 
202
159
  1. Open your GraphQL IDE (such as Postman) and make a `POST` request with the following details:
203
- - **URL:** https://{shop}.myshopify.com/admin/api/2022-04/graphql.json
204
- - **Headers:** - X-Shopify-Access-Token: {access_token} - Content-Type: application/json
205
- 2. Execute the following request to expose the `WidgetPreRenderStyleTag` Shop Metafield.
160
+
161
+ - **URL:** https://{shop}.myshopify.com/admin/api/2022-04/graphql.json
162
+ - **Headers:** - X-Shopify-Access-Token: {access_token} - Content-Type: application/json
163
+
164
+ 2. Execute the following request to expose the `WidgetPreRenderStyleTags` shop metafield:
206
165
 
207
166
  ```graphql
208
167
  mutation {
209
- metafieldStorefrontVisibilityCreate(
210
- input: {
211
- namespace: "okendo"
212
- key: "WidgetPreRenderStyleTags"
213
- ownerType: SHOP
214
- }
215
- ) {
216
- metafieldStorefrontVisibility {
217
- id
218
- }
219
- userErrors {
220
- field
221
- message
222
- }
223
- }
168
+ metafieldStorefrontVisibilityCreate(
169
+ input: {
170
+ namespace: "okendo"
171
+ key: "WidgetPreRenderStyleTags"
172
+ ownerType: SHOP
173
+ }
174
+ ) {
175
+ metafieldStorefrontVisibility {
176
+ id
177
+ }
178
+ userErrors {
179
+ field
180
+ message
181
+ }
182
+ }
224
183
  }
225
184
  ```
226
185
 
227
- 3. Execute the following request to expose the `WidgetPreRenderBodyStyleTags` Shop Metafield.
186
+ 3. Execute the following request to expose the `WidgetPreRenderBodyStyleTags` shop metafield:
228
187
 
229
188
  ```graphql
230
189
  mutation {
231
- metafieldStorefrontVisibilityCreate(
232
- input: {
233
- namespace: "okendo"
234
- key: "WidgetPreRenderBodyStyleTags"
235
- ownerType: SHOP
236
- }
237
- ) {
238
- metafieldStorefrontVisibility {
239
- id
240
- }
241
- userErrors {
242
- field
243
- message
244
- }
245
- }
190
+ metafieldStorefrontVisibilityCreate(
191
+ input: {
192
+ namespace: "okendo"
193
+ key: "WidgetPreRenderBodyStyleTags"
194
+ ownerType: SHOP
195
+ }
196
+ ) {
197
+ metafieldStorefrontVisibility {
198
+ id
199
+ }
200
+ userErrors {
201
+ field
202
+ message
203
+ }
204
+ }
246
205
  }
247
206
  ```
248
207
 
249
- 4. Execute the following request to expose the `ReviewsWidgetSnippet` Product Metafield.
208
+ 4. Execute the following request to expose the `ReviewsWidgetSnippet` product metafield:
250
209
 
251
210
  ```graphql
252
211
  mutation {
253
- metafieldStorefrontVisibilityCreate(
254
- input: {
255
- namespace: "okendo"
256
- key: "ReviewsWidgetSnippet"
257
- ownerType: PRODUCT
258
- }
259
- ) {
260
- metafieldStorefrontVisibility {
261
- id
262
- }
263
- userErrors {
264
- field
265
- message
266
- }
267
- }
212
+ metafieldStorefrontVisibilityCreate(
213
+ input: {
214
+ namespace: "okendo"
215
+ key: "ReviewsWidgetSnippet"
216
+ ownerType: PRODUCT
217
+ }
218
+ ) {
219
+ metafieldStorefrontVisibility {
220
+ id
221
+ }
222
+ userErrors {
223
+ field
224
+ message
225
+ }
226
+ }
268
227
  }
269
228
  ```
270
229
 
271
- 5. Execute the following request to expose the `StarRatingSnippet` the Product Metafield.
230
+ 5. Execute the following request to expose the `StarRatingSnippet` the product metafield:
272
231
 
273
232
  ```graphql
274
233
  mutation {
275
- metafieldStorefrontVisibilityCreate(
276
- input: { namespace: "okendo", key: "StarRatingSnippet", ownerType: PRODUCT }
277
- ) {
278
- metafieldStorefrontVisibility {
279
- id
280
- }
281
- userErrors {
282
- field
283
- message
284
- }
285
- }
234
+ metafieldStorefrontVisibilityCreate(
235
+ input: { namespace: "okendo", key: "StarRatingSnippet", ownerType: PRODUCT }
236
+ ) {
237
+ metafieldStorefrontVisibility {
238
+ id
239
+ }
240
+ userErrors {
241
+ field
242
+ message
243
+ }
244
+ }
286
245
  }
287
246
  ```
288
247
 
@@ -292,337 +251,290 @@ mutation {
292
251
  - [https://shopify.dev/api/admin-graphql/2022-04/mutations/metafieldstorefrontvisibilitycreate](https://shopify.dev/api/admin-graphql/2022-04/mutations/metafieldstorefrontvisibilitycreate)
293
252
  </details>
294
253
 
295
- <br/><br/>
296
-
297
- # How to Use Okendo Hydrogen Components In Your Hydrogen App <a id="how-to-use-okendo-hydrogen-components-in-your-hydrogen-app" name="3-how-to-use-okendo-hydrogen-components-in-your-hydrogen-app"></a>
298
-
299
254
  ## Installation
300
255
 
301
- 1. In your Hydrogen app directory, run `npm install @okendo/shopify-hydrogen` inside a terminal or PowerShell window.
302
- 2. **Optional:** Create (or add to) your `.env` file at the top level of your project (next to **hydrogen.config.ts**) the following, where `<your_subscriber_id>` is replaced with your Okendo Subscriber ID:
303
-
304
- ```sh
305
- # .env
306
- VITE_OKENDO_SUBSCRIBER_ID=<your_subscriber_id>
307
- ```
308
-
309
- 3. Open **vite.config.ts** and add `import okendo from '@okendo/shopify-hydrogen/plugin';` to the list of imports.
310
- 4. Add `okendo()` to the list of `plugins`.
311
-
312
- ```tsx
313
- /* vite.config.ts */
314
- /// <reference types="vitest" />
315
- import { defineConfig } from "vite";
316
- import hydrogen from "@shopify/hydrogen/plugin";
317
- import okendo from "@okendo/shopify-hydrogen/plugin";
318
-
319
- export default defineConfig({
320
- plugins: [hydrogen(), okendo()],
321
- resolve: {
322
- alias: [{ find: /^~\/(.*)/, replacement: "/src/$1" }],
323
- },
324
- optimizeDeps: {
325
- include: ["@headlessui/react", "clsx", "react-use", "typographic-base"],
326
- },
327
- test: {
328
- globals: true,
329
- testTimeout: 10000,
330
- hookTimeout: 10000,
331
- },
332
- });
333
- ```
334
-
335
- 5. Open **App.server.tsx** and import `OkendoProvider`.
336
- 6. Include the `OkendoProvider` as shown below, passing through your `subscriberId` from your Vite environment variables.
337
-
338
- ```tsx
339
- /* App.server.tsx */
340
- import {OkendoProvider} from '@okendo/shopify-hydrogen';
341
-
342
- function App() {
343
- return (
344
- <Suspense fallback={<LoadingFallback />}>
345
- <ShopifyProvider>
346
- <!-- *** Include OkendoProvider HERE *** -->
347
- <OkendoProvider
348
- subscriberId={import.meta.env.VITE_OKENDO_SUBSCRIBER_ID}
349
- />
350
- <ServerCartProvider>
351
- <DefaultSeo />
352
- <Router>
353
- <FileRoutes />
354
- <Route path="*" page={<NotFound />} />
355
- </Router>
356
- </ServerCartProvider>
357
- <PerformanceMetrics />
358
- {import.meta.env.DEV && <PerformanceMetricsDebug />}
359
- </ShopifyProvider>
360
- </Suspense>
361
- );
362
- ```
363
-
364
- If your app doesn't use Vite environment variables from a `.env` file, you could also provide your Okendo Subscriber ID through other means, i.e. directly:
365
-
366
- ```tsx
367
- <OkendoProvider subscriberId={okendoSubscriberId} />
368
- ```
369
-
370
- ## Widget Usage
371
-
372
- ### Server Components
373
-
374
- Import `OkendoReviewsWidget` and `OkendoStarRating` and use as JSX components. Pass in the Shopify Product ID as a prop.
375
-
376
- The `productId` prop is optional for the `OkendoReviewsWidget`. Not providing it will mean that the widget will display reviews for all products, which is ideal for homepages or collection pages.
256
+ > The code examples provided in this section are based on the [demo store provided by Shopify](https://github.com/Shopify/hydrogen/tree/2023-01/templates/demo-store). You will find the following steps already done in [our demo store](https://github.com/okendo/okendo-shopify-hydrogen-demo).
377
257
 
378
- ```tsx
379
- import {
380
- OkendoReviewsWidget,
381
- OkendoStarRating,
382
- } from '@okendo/shopify-hydrogen';
383
-
384
- ...
258
+ Run:
385
259
 
386
- const okendoReviewsWidget = <OkendoReviewsWidget productId={product.id} />;
387
- const okendoStarRating = <OkendoStarRating productId={product.id} />;
260
+ ```bash
261
+ npm i @okendo/shopify-hydrogen
388
262
  ```
389
263
 
390
- > ℹ️ &nbsp;Okendo `OkendoReviewsWidget` and `OkendoStarRating` widgets are server components. If you want to use them within a client component, you must pass the widget components as props to your client component. Widget components can be used directly in a server component. [Learn more here](#graphql-fragments).
391
-
392
- <br />
264
+ ### `app/root.tsx`
393
265
 
394
- ### Client Components
395
-
396
- #### Star Rating Widget Usage in Client Components
397
-
398
- We also include an `OkendoClientStarRating` component for use within client-side (e.g.`<your component>.client.tsx`) components.
399
-
400
- Import the `OkendoClientStarRating` component inside a client component and use as a JSX component as seen below:
401
-
402
- ```tsx
403
- import { OkendoClientStarRating } from '@okendo/shopify-hydrogen';
266
+ Open `app/root.tsx` and add the following import:
404
267
 
405
- ...
406
-
407
- const okendoClientStarRating = <OkendoClientStarRating productId={product.id} />;
268
+ ```ts
269
+ import {
270
+ OkendoProvider,
271
+ getOkendoProviderData,
272
+ } from "@okendo/shopify-hydrogen";
408
273
  ```
409
274
 
410
- > ℹ️ &nbsp;OPTIONAL: You can render the `OkendoClientStarRating` component without making any client-side network requests by using an optional prop `okendoStarRatingSnippet`. This can be achieved using a GraphQL Fragment. [Learn more here](#graphql-fragments).
411
-
412
- <br />
413
-
414
- # Components <a id="components" name="components"></a>
415
-
416
- ### OkendoProvider
417
-
418
- Top level component for enabling Okendo Widgets.
419
-
420
- We recommend using it directly inside the `<ShopifyProvider>` as its first child in **App.server.tsx**.
421
-
422
- It will provide:
423
-
424
- - Okendo Subscriber settings
425
- - Okendo widget CSS, including:
426
- - Base variables
427
- - Custom CSS specified in the Okendo Admin (if applicable)
428
- - "Above the fold" CSS essential for Server-Side Rendered (SSR) widgets. This ensures styled widgets prior to client-side hydration.
429
- - Okendo widget initialisation script
430
- - Used to render/hydrate widgets on the page
275
+ Locate the `meta` function, and append the property `oke:subscriber_id` containing your Okendo subscriber ID:
431
276
 
432
- | Name | Type | Description | Required |
433
- | ------------------------------------- | ----------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- |
434
- | <code>subscriberId</code> | <code>string</code> | The Okendo subscriber ID. | yes |
435
- | <code>apiDomain</code> | <code>string</code> | To override the default Okendo API Domain. (Default: <code>api.okendo.io/v1</code>) | no |
436
- | <code>cdnDomain</code> | <code>string</code> | To override the default Okendo CDN domain. (Default: <code>cdn-static.okendo.io</code>) | no |
437
- | <code>productUrlFormatOverride</code> | <code>(product: ReviewProduct) => string</code> | By default, we use Hydrogen's out of the box product routing.<br />**Advanced Usage Only:** Function hook which allows the custom configuration of the Shopify product URLs from the Okendo Reviews Widget. | no |
438
-
439
- ### OkendoReviewsWidget<a id="components--okendo-reviews-widget" name="components--okendo-reviews-widget"></a>
440
-
441
- The Okendo Reviews List widget.
442
-
443
- | Name | Type | Description | Required |
444
- | ---------------------- | ------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- |
445
- | <code>productId</code> | <code>string</code> | The Shopify Product ID. If provided, the Reviews Widget will be configured to display reviews specific to that product. Otherwise, the Reviews Widget will display reviews for all products. | no |
446
-
447
- ### OkendoStarRating<a id="components--okendo-star-rating" name="components--okendo-star-rating"></a>
448
-
449
- The Okendo Star Rating widget - **For use in _server_ components**.
450
-
451
- | Name | Type | Description | Required |
452
- | ---------------------- | ------------------- | ----------------------- | -------- |
453
- | <code>productId</code> | <code>string</code> | The Shopify Product ID. | yes |
277
+ ```ts
278
+ 'oke:subscriber_id': '<your-okendo-subscriber-id>',
279
+ ```
454
280
 
455
- <br/>
281
+ The `meta` function should now look like the following:
456
282
 
457
- ### OkendoClientStarRating<a id="components--okendo-client-star-rating" name="components--okendo-client-star-rating"></a>
283
+ ```ts
284
+ export const meta: MetaFunction = () => ({
285
+ charset: "utf-8",
286
+ viewport: "width=device-width,initial-scale=1",
287
+ "oke:subscriber_id": "<your-okendo-subscriber-id>",
288
+ });
289
+ ```
458
290
 
459
- The Okendo Star Rating widget - **For use in _client_ components**.
291
+ Locate the `loader` function and append the `okendoProviderData` property to the returned data:
460
292
 
461
- | Name | Type | Description | Required |
462
- | ------------------------------------ | -------------------------------------------------- | --------------------------------------------------------------- | -------- |
463
- | <code>productId</code> | <code>string</code> | The Shopify Product ID. | yes |
464
- | <code>okendoStarRatingSnippet</code> | <code>Pick<Metafield, "value"> \| undefined</code> | The server-side pre-rendered markup representing a star snippet | no |
293
+ ```ts
294
+ okendoProviderData: await getOkendoProviderData({
295
+ context,
296
+ subscriberId: '<your-okendo-subscriber-id>',
297
+ }),
298
+ ```
465
299
 
466
- <br/>
300
+ The `loader` function returned data should now look like the following:
301
+
302
+ ```ts
303
+ return defer({
304
+ isLoggedIn: Boolean(customerAccessToken),
305
+ layout,
306
+ selectedLocale: context.storefront.i18n,
307
+ cart: cartId ? getCart(context, cartId) : undefined,
308
+ analytics: {
309
+ shopifySalesChannel: ShopifySalesChannel.hydrogen,
310
+ shopId: layout.shop.id,
311
+ },
312
+ seo,
313
+ okendoProviderData: await getOkendoProviderData({
314
+ context,
315
+ subscriberId: "<your-okendo-subscriber-id>",
316
+ }),
317
+ });
318
+ ```
467
319
 
468
- ---
320
+ Locate the `App` function, append `OkendoProvider` to `body`, and provide it with the data returned by `getOkendoProviderData`:
469
321
 
470
- # GraphQL Fragments <a id="graphql-fragments" name="graphql-fragments"></a>
322
+ ```tsx
323
+ ...
324
+ <body>
325
+ <OkendoProvider okendoProviderData={data.okendoProviderData} />
326
+ ...
327
+ </body>
328
+ ...
329
+ ```
471
330
 
472
- A GraphQL fragment is a piece of logic that can be shared between multiple queries and mutations.
331
+ ### `app/data/fragments.ts`
473
332
 
474
- We offer performance benefits even when using our client Star Rating Widget by exposing an `OKENDO_PRODUCT_STAR_RATING_FRAGMENT` GraphQL Fragment for use in your server components.
333
+ Open `app/data/fragments.ts` and add the following import:
475
334
 
476
- This allows you to fetch pre-rendered markup in a **server component** for use within the client component (usually passed down as a property from the server component to the client).
335
+ ```ts
336
+ import { OKENDO_PRODUCT_STAR_RATING_FRAGMENT } from "@okendo/shopify-hydrogen";
337
+ ```
477
338
 
478
- If the pre-rendered mark-up is present, the star rating widget initialization does not occur in the client, offering performance benefits.
339
+ Then add `${OKENDO_PRODUCT_STAR_RATING_FRAGMENT}` and `...OkendoStarRatingSnippet` to `PRODUCT_CARD_FRAGMENT`:
340
+
341
+ ```ts
342
+ export const PRODUCT_CARD_FRAGMENT = `#graphql
343
+ ${OKENDO_PRODUCT_STAR_RATING_FRAGMENT}
344
+ fragment ProductCard on Product {
345
+ id
346
+ title
347
+ publishedAt
348
+ handle
349
+ ...OkendoStarRatingSnippet
350
+ variants(first: 1) {
351
+ ...
352
+ ```
479
353
 
480
- <br/>
354
+ ### `app/components/ProductCard.tsx`
481
355
 
482
- ## Example: Using GraphQL Framgment with OkendoClientStarRating
356
+ Open `app/components/ProductCard.tsx` and add the following import:
483
357
 
484
- > ℹ️ &nbsp;NOTE: The following example usage is based on our Okendo Hydrogen Demo Store. Refer to the [Github repo](https://github.com/okendo/okendo-shopify-hydrogen-demo) to see a working example.
358
+ ```ts
359
+ import {
360
+ OkendoStarRating,
361
+ WithOkendoStarRatingSnippet,
362
+ } from "@okendo/shopify-hydrogen";
363
+ ```
485
364
 
486
- <br/>
365
+ Tweak the type of the `product` prop to be:
487
366
 
488
- In the sample [Okendo Hydrogen Demo Store](https://github.com/okendo/okendo-shopify-hydrogen-demo) we extend the `PRODUCT_CARD_FRAGMENT` with our `OKENDO_PRODUCT_STAR_RATING_FRAGMENT`.
367
+ ```ts
368
+ product: SerializeFrom<Product & WithOkendoStarRatingSnippet>;
369
+ ```
489
370
 
490
- Open `ProductGrid.client.tsx` and make the changes to the `PRODUCT_CARD_FRAGMENT` as seen below:
371
+ `ProductCard` should now look like this:
491
372
 
492
- <br/>
373
+ ```ts
374
+ export function ProductCard({
375
+ product,
376
+ label,
377
+ className,
378
+ loading,
379
+ onClick,
380
+ quickAdd,
381
+ }: {
382
+ product: SerializeFrom<Product & WithOkendoStarRatingSnippet>;
383
+ label?: string;
384
+ className?: string;
385
+ loading?: HTMLImageElement['loading'];
386
+ onClick?: () => void;
387
+ quickAdd?: boolean;
388
+ }) {
389
+ ```
493
390
 
494
- **Before**
391
+ Add the `OkendoStarRating` component:
495
392
 
496
393
  ```tsx
497
- export const PRODUCT_CARD_FRAGMENT = gql`
498
- fragment ProductCard on Product {
499
- id
500
- title
501
- publishedAt
502
- handle
503
- variants(first: 1) {
504
- nodes {
505
- id
506
- image {
507
- url
508
- altText
509
- width
510
- height
511
- }
512
- priceV2 {
513
- amount
514
- currencyCode
515
- }
516
- compareAtPriceV2 {
517
- amount
518
- currencyCode
519
- }
520
- }
521
- }
522
- }
523
- `;
394
+ <OkendoStarRating
395
+ productId={product.id}
396
+ okendoStarRatingSnippet={product.okendoStarRatingSnippet}
397
+ />
524
398
  ```
525
399
 
526
- **After**
400
+ For instance, you can add it below the product title, like this:
527
401
 
528
402
  ```tsx
529
- export const PRODUCT_CARD_FRAGMENT = gql`
530
- ${OKENDO_PRODUCT_STAR_RATING_FRAGMENT}
531
- fragment ProductCard on Product {
532
- id
533
- title
534
- publishedAt
535
- handle
536
- ...OkendoStarRatingSnippet
537
- variants(first: 1) {
538
- nodes {
539
- id
540
- image {
541
- url
542
- altText
543
- width
544
- height
545
- }
546
- priceV2 {
547
- amount
548
- currencyCode
549
- }
550
- compareAtPriceV2 {
551
- amount
552
- currencyCode
553
- }
554
- }
555
- }
556
- }
557
- `;
403
+ <Text
404
+ className="w-full overflow-hidden whitespace-nowrap text-ellipsis "
405
+ as="h3"
406
+ >
407
+ {product.title}
408
+ </Text>
409
+ <OkendoStarRating
410
+ productId={product.id}
411
+ okendoStarRatingSnippet={product.okendoStarRatingSnippet}
412
+ />
558
413
  ```
559
414
 
560
- Adding the `OKENDO_PRODUCT_STAR_RATING_FRAGMENT` GraphQL Fragment allows you to access and include an `okendoStarRatingSnippet` in your `Product` query.
561
-
562
- The `okendoStarRatingSnippet` is a server-side rendered version of the output of your star rating contents. This is supplied to your `Product`/`Collection` queries using the `OKENDO_PRODUCT_STAR_RATING_FRAGMENT` to fetch a metafield containg the markup.
415
+ ### `app/routes/($lang)/products/$productHandle.tsx`
563
416
 
564
- To help with typing we have exposed an `OkendoProductFragment` type which can be used as a union type with an existing Hydrogen `Product` type.
417
+ Open `app/routes/($lang)/products/$productHandle.tsx` and add the following imports:
565
418
 
566
- For this example we have used `ProductCard.client.tsx` from our Okendo Hydrogen Demo App.
419
+ ```ts
420
+ import {
421
+ OkendoReviews,
422
+ OkendoStarRating,
423
+ WithOkendoStarRatingSnippet,
424
+ WithOkendoReviewsSnippet,
425
+ OKENDO_PRODUCT_STAR_RATING_FRAGMENT,
426
+ OKENDO_PRODUCT_REVIEWS_FRAGMENT,
427
+ } from "@okendo/shopify-hydrogen";
428
+ ```
567
429
 
568
- The `ProductCard.client.tsx` component has the result of a server-side `useShopQuery` passed down as props to it.
430
+ In the storefront query, tweak the type of `product` to be:
569
431
 
570
- Because we have implemented our `OKENDO_PRODUCT_STAR_RATING_FRAGMENT` we can express the resulting type as a union:
432
+ ```ts
433
+ product: ProductType & {
434
+ selectedVariant?: ProductVariant;
435
+ } & WithOkendoStarRatingSnippet &
436
+ WithOkendoReviewsSnippet;
437
+ ```
571
438
 
572
- ```tsx
573
- Product & OkendoProductFragment
439
+ The storefront query should now look like this:
440
+
441
+ ```ts
442
+ const { shop, product } = await context.storefront.query<{
443
+ product: ProductType & {
444
+ selectedVariant?: ProductVariant;
445
+ } & WithOkendoStarRatingSnippet &
446
+ WithOkendoReviewsSnippet;
447
+ shop: Shop;
448
+ }>(PRODUCT_QUERY, {
449
+ variables: {
450
+ handle: productHandle,
451
+ selectedOptions,
452
+ country: context.storefront.i18n.country,
453
+ language: context.storefront.i18n.language,
454
+ },
455
+ });
574
456
  ```
575
457
 
576
- In the `ProductCard.client.tsx` import the `OkendoProductFragment` type and the `OkendoClientStarRating` component:
458
+ Add the `OkendoStarRating` component:
577
459
 
578
460
  ```tsx
579
- import type { OkendoProductFragment } from "@okendo/shopify-hydrogen";
580
- import { OkendoClientStarRating } from "@okendo/shopify-hydrogen/client";
461
+ <OkendoStarRating
462
+ productId={product.id}
463
+ okendoStarRatingSnippet={product.okendoStarRatingSnippet}
464
+ />
581
465
  ```
582
466
 
583
- The constructor of the `ProductCard.client.tsx` component can then be modified to use a union-type for the `Product` being passed in to the constructor:
467
+ For instance, you can add it between the product title and the store name, like this:
584
468
 
585
469
  ```tsx
586
- export function ProductCard({
587
- product,
588
- label,
589
- className,
590
- loading,
591
- onClick,
592
- }: {
593
- product: Product & OkendoProductFragment;
594
- label?: string;
595
- className?: string;
596
- loading?: HTMLImageElement['loading'];
597
- onClick?: () => void;
598
- }) {
599
- ...
600
- }
470
+ <Heading as="h1" className="whitespace-normal">
471
+ {title}
472
+ </Heading>
473
+ <OkendoStarRating
474
+ productId={product.id}
475
+ okendoStarRatingSnippet={product.okendoStarRatingSnippet}
476
+ />
477
+ {vendor && (
478
+ <Text className={'opacity-50 font-medium'}>{vendor}</Text>
479
+ )}
601
480
  ```
602
481
 
603
- Import the `OkendoClientStarRating` component inside the client component and use as seen below. Pass in `product.okendoStarRatingSnippet` as the value for the optional prop `okendoStarRatingSnippet`. This will use the pre-rendered value of the star rating markup without having to make any client-side network requests.
482
+ Add the `OkendoReviews` component:
604
483
 
605
484
  ```tsx
606
- {
607
- product.okendoStarRatingSnippet?.value ? (
608
- <OkendoClientStarRating
609
- productId={product.id}
610
- okendoStarRatingSnippet={product.okendoStarRatingSnippet}
611
- />
612
- ) : null;
613
- }
485
+ <OkendoReviews
486
+ productId={product.id}
487
+ okendoReviewsSnippet={product.okendoReviewsSnippet}
488
+ />
614
489
  ```
615
490
 
616
- **References**
617
-
618
- - [GraphQL Fragments](https://www.apollographql.com/docs/react/data/fragments/)
491
+ For instance, you can add it below the product section:
619
492
 
620
- ---
621
-
622
- <br/>
493
+ ```tsx
494
+ ...
495
+ </Section>
496
+ <OkendoReviews
497
+ productId={product.id}
498
+ okendoReviewsSnippet={product.okendoReviewsSnippet}
499
+ />
500
+ <Suspense fallback={<Skeleton className="h-32" />}>
501
+ ...
502
+ ```
623
503
 
624
- ## View Our Okendo Sample Hydrogen App <a id="view-our-okendo-sample-hydrogen-app" name="view-our-okendo-sample-hydrogen-app"></a>
504
+ Locate `PRODUCT_QUERY` and add the following to it:
625
505
 
626
- We have created a Shopify Hydrogen sample application with our widgets pre-installed.
506
+ ```ts
507
+ ...
508
+ ${OKENDO_PRODUCT_STAR_RATING_FRAGMENT}
509
+ ${OKENDO_PRODUCT_REVIEWS_FRAGMENT}
510
+ ...
511
+ ...OkendoStarRatingSnippet
512
+ ...OkendoReviewsSnippet
513
+ ```
627
514
 
628
- - [View our Sample Okendo Shopify Hydrogen Demo Repository](https://github.com/okendo/okendo-shopify-hydrogen-demo)
515
+ It should now look like this:
516
+
517
+ ```ts
518
+ const PRODUCT_QUERY = `#graphql
519
+ ${MEDIA_FRAGMENT}
520
+ ${PRODUCT_VARIANT_FRAGMENT}
521
+ ${OKENDO_PRODUCT_STAR_RATING_FRAGMENT}
522
+ ${OKENDO_PRODUCT_REVIEWS_FRAGMENT}
523
+ query Product(
524
+ $country: CountryCode
525
+ $language: LanguageCode
526
+ $handle: String!
527
+ $selectedOptions: [SelectedOptionInput!]!
528
+ ) @inContext(country: $country, language: $language) {
529
+ product(handle: $handle) {
530
+ id
531
+ title
532
+ vendor
533
+ handle
534
+ descriptionHtml
535
+ description
536
+ ...OkendoStarRatingSnippet
537
+ ...OkendoReviewsSnippet
538
+ options {
539
+ ...
540
+ ```