@okendo/shopify-hydrogen 1.3.1 → 2.0.1

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