@ekolabs/eko-gallery-react
Version:
eko gallery for react framework
296 lines (216 loc) • 10.8 kB
Markdown
# Eko Gallery React
A library for integrating the [eko](https://eko.com) gallery into your react based site.
## Installation
```bash
npm install @ekolabs/eko-gallery-react
```
OR
```bash
yarn add @ekolabs/eko-gallery-react
```
## Usage
### EkoGallery Component
The `EkoGallery` component is used to render the eko gallery on your site. It should replace your existing product gallery component.
```jsx
import { EkoGallery } from '@ekolabs/eko-gallery-react';
<EkoGallery
className="mb-4"
config={config}
variantId={variantId}
activeItem={activeItem}
ref={galleryRef}
onEvent={onEkoGalleryEvent}
>
{/* Your existing product gallery component that will serve as a fallback */}
<CustomerGalley />
</EkoGallery>
```
This component accepts the following props:
| Prop | Type | Description |
|------------|----------|-------------------------------------------------------------------------------------------------------------------------------------------------|
| className | String | _Optional._ class names to add to the `EkoGallery` component, for styling purposes for example. |
| config | Object | The eko gallery configuration. This object will be published via the eko platform and exposed via an api endpoint (see below). |
| variantId | String | _Optional._ The selected variant (if applicable). It is used to switch to the relevant variant gallery assets when the product variant changes. |
| activeItem | Object | _Optional._ Updates the displayed item and step of the EkoGallery. |
| ref | Object | _Optional._ Exposes the next() and prev() functions that allow navigation between the steps |
| onEvent | Function | _Optional._ Handler for events occurred in the eko gallery, for third party tools tracking for example. |
> When passing the `onEvent` prop, make sure to use the `useCallback()` hook to avoid unnecessary re-renders.
### Enabling SSR
To enable SSR of the EkoGallery you'll need to add the `ssrHtml` prop to `<EkoGallery>`.
To get `ssrHtml` on the server, import `getSsrHtml` from `@ekolabs/eko-gallery-react/server` and pass it to `<EkoGallery>`.
```jsx
// Next.js example
import { EkoGallery } from '@ekolabs/eko-gallery-react';
const EKO_SALES_CHANNEL_ID = process.env.EKO_SALES_CHANNEL_ID;
export async function getStaticProps({ params: { id } }) {
const { getSsrHtml } = await import('@ekolabs/eko-gallery-react/server');
const ekoProductConfigUrl = getEkoProductConfigUrl(EKO_SALES_CHANNEL_ID);
const ekoProductResponse = await fetch(ekoProductConfigUrl).then(res => res.json());
const ekoProductConfigs = ekoProductResponse.data;
const config = ekoProductConfigs[id];
const { ssrHtml } = await getSsrHtml(config);
return {
props: {
ekoGalleryProps: {
config,
ssrHtml
}
}
};
}
export default function ProductPage({ ekoGalleryProps }) {
return (
<EkoGallery
{...ekoGalleryProps}
// rest of EkoGallery props...
>
);
}
```
The dynamic import in `getStaticProps` ensures that `@ekolabs/eko-gallery-react/server` doesn't get bundled into your next.js client's code.
#### getSsrHtml(config, isForMobile)
| Arg | Type | Description |
|-------------|---------|---------------------------------------------------------------------------------------------------------------------|
| config | Object | The config for the product as recieved from eko |
| isForMobile | Boolean | If you know on the server that the client is a mobile device pass `true` so the resulting layout will be for mobile |
### Switching the gallery's active item externally example
First, initialize a variable using React's `useRef()` hook.
Then, pass it to the `ref` property of the `EkoGallery` component.
This enables to call two functions:
1. `next()` - Will cycle to the next step of an active item. When called on the last step of an active item - the gallery will cycle to the first step of the next index.
2. `prev()` - Will cycle to the previous step of an active item. When called on the first step of an active item - the gallery will cycle to last step of the previous index.
```js
import { useRef } from 'react';
const galleryRef = useRef(null);
// Call the gallery's next() method to cycle to the next step.
function onNextClick() {
galleryRef.current.next();
}
// Call the gallery's prev() method to cycle to the previous step.
function onPrevClick() {
galleryRef.current.prev();
}
```
### Config data fetching
To get the eko product configs, you should use the `getEkoProductConfigUrl()` function to get the url, fetch the data and pass it to the `EkoGallery` component.
The `getEkoProductConfigUrl()` receives the eko sales channel id and returns the url to fetch the eko product configs from.
```js
import { getEkoProductConfigUrl } from '@ekolabs/eko-gallery-react';
const EKO_SALES_CHANNEL_ID = process.env.EKO_SALES_CHANNEL_ID;
const ekoProductConfigUrl = getEkoProductConfigUrl(EKO_SALES_CHANNEL_ID);
const ekoProductResponse = await fetch(ekoProductConfigUrl).then(res => res.json());
const ekoProductConfigs = ekoProductResponse.data;
```
### Analytics setup
Our 1st party tracking tool should be added in order to track events on the site.
#### The eko analytics snippet
The eko analytics snippet should be added to the site's head tag, here is an example in `Next.js`:
```jsx
// _document.tsx
import Script from 'next/script';
import { getEkoAnalyticsSnippet } from '@ekolabs/eko-gallery-react';
const IS_PRODUCTION = process.env.NODE_ENV === 'production';
render() {
return (
<Html lang="en">
<Head>
<Script id="eko-analytics-snippet" strategy="beforeInteractive">
{getEkoAnalyticsSnippet(IS_PRODUCTION)}
</Script>
</Head>
<body>
<Main />
<NextScript />
</body>
</Html>
);
}
```
### Events
The eko gallery dispatches events through the `onEvent` handler. Use this to track user interactions and gallery lifecycle events.
#### Event Types
| Event | Description |
|---------------------|-------------------------------------------------------------------|
| `galleryinit` | Fired when the gallery component initializes |
| `galleryloaded` | Fired when the interactive smart gallery is fully loaded |
| `activeitemchanged` | Fired when the active gallery item changes |
| `click` | Fired when the user click on a non-interactive part of the video |
| `swipe` | Fired when the user swipes within the interactive video |
| `interaction` | Fired on any user interaction (click, swipe, etc.) with interaction metadata |
#### Event Payloads
##### `activeitemchanged` event
Fired when the displayed gallery item changes (via thumbnail click, carousel scroll, or internal navigation).
| Property | Type | Description |
| -------- | ---- | ----------- |
| `index` | Number | The zero-based index of the newly active item |
| `step` | Number | The zero-based index of the newly active item's step/sub-item |
##### `click` event
| Property | Type | Description |
|---------------|--------|----------------------------|
| `x` | Number | x value of the click event |
| `y` | Number | y value of the click event |
##### `swipe` event
Fired when the user swipes within the interactive video.
##### `interaction` event
Fired on any user interaction, providing structured metadata about the interaction.
| Property | Type | Description |
|-------------------|--------|--------------------------------------------------------------------|
| `elementid` | String | Identifier of the interacted element |
| `elementtype` | String | Type of the interacted element |
| `elementname` | String | Name of the interacted element |
| `interactiontype` | String | Type of interaction (e.g. `swipe_next`, `swipe_prev`) |
##### Lifecycle events (`galleryinit`, `gallerycoverdisplayed`, `galleryloaded`)
These events are fired without a payload and indicate gallery state transitions.
#### Example
```jsx
const onEkoGalleryEvent = useCallback((event, data) => {
switch (event) {
case 'galleryinit':
console.log('Gallery initialized');
break;
case 'galleryloaded':
console.log('Interactive gallery ready');
break;
case 'activeitemchanged':
console.log(`Active item changed to: ${data.index} ${data.step}`);
break;
case 'click':
console.log(`Click: ${data}`);
break;
case 'swipe':
console.log('User swiped in interactive video', data);
break;
case 'interaction':
console.log(`Interaction: ${data.interactiontype} on ${data.elementid}`);
break;
}
}, []);
```
#### ekoWebPixel
The `ekoWebPixel` API is used to track the events on your site.
Init once via the `init()` method:
```jsx
import { ekoWebPixel } from '@ekolabs/eko-gallery-react';
const IS_PRODUCTION = process.env.NODE_ENV === 'production';
useEffect(() => {
ekoWebPixel.init(IS_PRODUCTION);
}, []);
```
Track events via the `track()` method:
```jsx
import { ekoWebPixel } from '@ekolabs/eko-gallery-react';
ekoWebPixel.track('pixel.page_viewed');
ekoWebPixel.track('pixel.product_viewed', { ... });
ekoWebPixel.track('pixel.cart.add', { ... });
ekoWebPixel.track('pixel.cart.remove', { ... });
// For traffic allocation:
ekoWebPixel.track('trafficallocation.decision', { ... });
// For non shopify backend stores:
ekoWebPixel.track('pixel.checkout', { ... });
ekoWebPixel.track('pixel.order', { ... });
```
Report on route changes:
```jsx
import { ekoWebPixel } from '@ekolabs/eko-gallery-react';
ekoWebPixel.onRouteChanged();
```