@glood/hydrogen
v0.2.1
Published
Glood SDK for Shopify Hydrogen - React components and hooks for seamless e-commerce integration
Maintainers
Readme
@glood/hydrogen
Glood SDK for Shopify Hydrogen - React components and hooks for seamless e-commerce integration.
Features
🚀 Hydrogen-Optimized - Built specifically for Shopify Hydrogen framework 🛍️ Recommendations - Load recommendation sections with full product data via hook or SSR loader 📡 Zero-Config Analytics - Standard events (page views, add to cart, …) sent out of the box 🎯 TypeScript First - Full type safety with excellent developer experience ⚡ Performance Focused - Tree-shakeable exports and optimized for SSR 🔧 Developer Friendly - Minimal configuration with sensible defaults 📦 Lightweight - Small bundle size with no unnecessary dependencies
Installation
npm install @glood/hydrogen
# or
yarn add @glood/hydrogen
# or
pnpm add @glood/hydrogenQuick Start
1. Install Environment Variables
Add your Glood API key to your environment variables:
# .env
GLOOD_API_KEY=your_glood_api_key_here2. Configure the Glood Client
// app/root.tsx
import { Analytics } from '@shopify/hydrogen';
import { GloodProvider, createGlood } from '@glood/hydrogen';
import { recommendations } from '@glood/hydrogen/recommendations';
import { search } from '@glood/hydrogen/search';
import { wishlist } from '@glood/hydrogen/wishlist';
import { useLoaderData } from 'react-router';
const glood = createGlood({
apiKey: process.env.GLOOD_API_KEY!,
myShopifyDomain: 'your-store.myshopify.com',
})
.use(recommendations())
.use(search())
.use(wishlist());
export default function App() {
const loaderData = useLoaderData();
return (
<Analytics>
<GloodProvider client={glood} loaderData={loaderData}>
<Outlet />
</GloodProvider>
</Analytics>
);
}3. That's It! 🎉
No additional setup required. The SDK automatically:
- ✅ Tracks user interactions via Shopify Analytics
- ✅ Sends pixel events to Glood endpoints
- ✅ Respects customer privacy settings
- ✅ Provides debug logging in development
Configuration Fields
Required Fields
| Field | Type | Description |
|-------|------|-------------|
| apiKey | string | Your Glood API key for authentication |
| myShopifyDomain | string | Your Shopify store domain (e.g., 'my-store.myshopify.com') |
Basic Configuration
For most use cases, you only need these two fields:
const glood = createGlood({
apiKey: process.env.GLOOD_API_KEY!,
myShopifyDomain: 'your-store.myshopify.com',
})
.use(recommendations())
.use(search())
.use(wishlist());The SDK will automatically use default endpoints and enable pixel tracking for all apps.
Advanced Configuration
For advanced use cases, you can customize endpoints and pixel settings:
Advanced Fields
| Field | Type | Description |
|-------|------|-------------|
| apps | object | Custom configuration for each app module |
| debug | boolean | Enable debug logging in development |
App Configuration
Each app in the apps object can be configured with:
| Field | Type | Description |
|-------|------|-------------|
| endpoint | string | Main endpoint for app features and API calls |
| pixel.enabled | boolean | Enable/disable pixel tracking for this app |
| pixel.endpoint | string | Endpoint for sending pixel tracking events |
| pixel.consent | ConsentType[] | Required consent types for sending pixel events |
Advanced Usage Example
const glood = createGlood({
apiKey: process.env.GLOOD_API_KEY!,
myShopifyDomain: 'your-store.myshopify.com',
apps: {
recommendations: {
endpoint: 'https://storefront.glood.ai',
pixel: {
enabled: true,
endpoint: 'https://events.glood.ai',
consent: ['analytics', 'marketing'],
},
},
search: {
endpoint: 'https://s-s.glood.ai',
pixel: {
enabled: true,
endpoint: 'https://s-pixel.glood.ai',
consent: ['analytics'],
},
},
wishlist: {
endpoint: 'https://w-s.glood.ai',
pixel: {
enabled: false, // Disable pixel tracking for wishlist
endpoint: 'https://w-pixel.glood.ai',
consent: ['analytics', 'preferences'],
},
},
},
debug: process.env.NODE_ENV === 'development',
})
.use(recommendations())
.use(search())
.use(wishlist());Default Endpoints
When using basic configuration, these endpoints are used automatically:
Recommendations
- Main:
https://storefront.glood.ai- Product recommendations and storefront features - Pixel:
https://events.glood.ai- Analytics events tracking
Search
- Main:
https://s-s.glood.ai- Search functionality and API - Pixel:
https://s-pixel.glood.ai- Search analytics tracking
Wishlist
- Main:
https://w-s.glood.ai- Wishlist management features - Pixel:
https://w-pixel.glood.ai- Wishlist analytics tracking
Where to Add the Provider
The GloodProvider must be added to your root layout file (app/root.tsx) and should:
- Be wrapped inside Shopify's
<Analytics>component - This ensures proper integration with Hydrogen's analytics system - Wrap your entire application routes - Usually around
<Outlet /> - Be placed at the root level - So all routes have access to Glood functionality
- Receive loaderData prop - This provides apps access to Hydrogen's loader data for enhanced functionality
Why loaderData is Required
The loaderData prop is mandatory and enables Glood apps to:
- Access route-specific data from Hydrogen loaders
- Enhance analytics events with additional context
- Provide personalized recommendations based on current page data
- Optimize search results using page context
Always pass the result of useLoaderData() to the GloodProvider:
❌ Incorrect Placement
// DON'T do this - missing Analytics wrapper and loaderData
export default function App() {
return (
<GloodProvider client={glood}>
<Outlet />
</GloodProvider>
);
}✅ Correct Placement
// DO this - properly wrapped in Analytics with loaderData
import { Analytics } from '@shopify/hydrogen';
import { useLoaderData } from 'react-router';
export default function App() {
const loaderData = useLoaderData();
return (
<Analytics>
<GloodProvider client={glood} loaderData={loaderData}>
<Outlet />
</GloodProvider>
</Analytics>
);
}Loading Recommendations
Fetch Glood-configured recommendation sections with full product data (title, handle, price, compare-at price, images, options, variants).
Client-side: useRecommendations hook
Use inside <GloodProvider>. pageUrl, locale, and the Glood client id are auto-filled from the browser:
import { useRecommendations } from '@glood/hydrogen';
function ProductRecommendations({ productId }: { productId: string }) {
const { sections, loading, error, trackClick, trackAddToCart } =
useRecommendations({
pageType: 'product_page', // 'product_page' | 'collection' | 'home' | 'cart' | ...
productId, // numeric Shopify product id
});
if (loading || error) return null;
return sections.map(section => (
<section key={section.section_serve_id}>
<h2>{section.title}</h2>
{section.products.map(product => (
<a
key={product.product_id}
href={`/products/${product.handle}`}
onClick={() =>
trackClick({
section: String(section.id),
sectionServeId: section.section_serve_id,
products: [{ productId: String(product.product_id) }],
})
}
>
{product.title} — {product.price}
</a>
))}
</section>
));
}The hook also returns data (the full API response), refetch(), and attribution helpers (trackRender, trackView, trackClick, trackAddToCart) that emit glood:section:* events so recommendation views and clicks are attributed to revenue in Glood analytics.
Server-side: fetchRecommendationSections (SSR)
For rendering recommendations in the initial HTML, fetch in a Hydrogen route loader. Pass pageUrl and locale explicitly (no browser context on the server):
import { fetchRecommendationSections } from '@glood/hydrogen';
export async function loader({ request, params, context }) {
const recommendations = await fetchRecommendationSections(
{
apiKey: context.env.GLOOD_API_KEY,
myShopifyDomain: 'your-store.myshopify.com',
},
{
pageType: 'product_page',
pageUrl: request.url,
locale: 'en-US',
productId: params.productId,
}
).catch(() => null); // never let recommendations break the page
return { recommendations };
}Throws GloodApiError (with status and body) on API failures.
See examples/basic/recommendations-page.tsx for a complete example, and specs/recommendations-and-pixel-events.md for the full API contract.
Pixel Events
The SDK automatically tracks user interactions through Shopify's Analytics system and sends pixel events to Glood endpoints. No manual event tracking is required.
How Pixel Tracking Works
- Automatic Subscription:
GloodProvidersubscribes to Shopify Analytics events - Event Filtering: Events are filtered based on your app configuration
- Pixel Transmission: Relevant events are sent to enabled pixel endpoints
- Consent Handling: Respects Shopify's Customer Privacy API automatically
Tracked Events
| Event | Triggered When | Sent To |
|-------|---------------|---------|
| page_viewed | User navigates to any page | All enabled pixel endpoints |
| product_viewed | User views a product page | Recommendations pixel (if enabled) |
| search_viewed | User performs a search | Search pixel (if enabled) |
| collection_viewed | User views a collection | Recommendations pixel (if enabled) |
| cart_viewed | User views their cart | All enabled pixel endpoints |
Controlling Pixel Tracking
You can enable or disable pixel tracking per app:
// Basic configuration - pixel tracking enabled by default
const glood = createGlood({
apiKey: process.env.GLOOD_API_KEY!,
myShopifyDomain: 'your-store.myshopify.com',
})
.use(recommendations())
.use(search())
.use(wishlist());
// Advanced configuration - custom pixel settings
const glood = createGlood({
apiKey: process.env.GLOOD_API_KEY!,
myShopifyDomain: 'your-store.myshopify.com',
apps: {
recommendations: {
endpoint: 'https://storefront.glood.ai',
pixel: {
enabled: true, // ✅ Pixel events will be sent
endpoint: 'https://events.glood.ai',
},
},
wishlist: {
endpoint: 'https://w-s.glood.ai',
pixel: {
enabled: false, // ❌ No pixel events sent
endpoint: 'https://w-pixel.glood.ai',
},
},
},
})
.use(recommendations())
.use(wishlist()); // Note: search not includedPrivacy and Consent
The SDK provides granular consent control per app to ensure privacy compliance:
Default Consent Requirements
In basic configuration, these consent requirements are used automatically:
- Recommendations:
['analytics', 'marketing']- Analytics processing and marketing consent - Search:
['analytics']- Only analytics consent required - Wishlist:
['analytics', 'preferences']- Analytics and preferences consent
Custom Consent Configuration
You can customize consent requirements for each app:
import { CONSENT_TYPES } from '@glood/hydrogen';
const glood = createGlood({
apiKey: process.env.GLOOD_API_KEY!,
myShopifyDomain: 'your-store.myshopify.com',
apps: {
recommendations: {
endpoint: 'https://storefront.glood.ai',
pixel: {
enabled: true,
endpoint: 'https://events.glood.ai',
// Only analytics consent required (minimal privacy impact)
consent: [CONSENT_TYPES.ANALYTICS],
},
},
search: {
endpoint: 'https://s-s.glood.ai',
pixel: {
enabled: true,
endpoint: 'https://s-pixel.glood.ai',
// Analytics + preferences (for search personalization)
consent: [CONSENT_TYPES.ANALYTICS, CONSENT_TYPES.PREFERENCES],
},
},
wishlist: {
endpoint: 'https://w-s.glood.ai',
pixel: {
enabled: true,
endpoint: 'https://w-pixel.glood.ai',
// Strictest privacy requirements
consent: [
CONSENT_TYPES.ANALYTICS,
CONSENT_TYPES.MARKETING,
CONSENT_TYPES.PREFERENCES,
CONSENT_TYPES.SALE_OF_DATA,
],
},
},
},
})
.use(recommendations())
.use(search())
.use(wishlist());Available Consent Types
import { CONSENT_TYPES } from '@glood/hydrogen';
// Available consent constants:
CONSENT_TYPES.ANALYTICS // 'analytics' - Basic analytics processing
CONSENT_TYPES.MARKETING // 'marketing' - Marketing and advertising
CONSENT_TYPES.PREFERENCES // 'preferences' - User preferences and personalization
CONSENT_TYPES.SALE_OF_DATA // 'sale_of_data' - Data selling to third partiesHow Consent Works
- User visits site and sees Shopify cookie banner
- User grants specific consent types through the privacy interface
- Events are tracked by Shopify Analytics as usual
- For each event, Glood checks if user has granted all required consents for that app
- Only if all consents are granted, pixel data is sent to Glood
Example Consent Scenarios
| User Consents | Recommendations Events | Search Events | Wishlist Events | |---------------|----------------------|---------------|-----------------| | None | ❌ Not sent | ❌ Not sent | ❌ Not sent | | Analytics only | ✅ Sent (needs analytics) | ❌ Not sent (needs preferences) | ❌ Not sent (needs marketing+) | | Analytics + Preferences | ✅ Sent | ✅ Sent | ❌ Not sent (needs marketing+) | | All consents | ✅ Sent | ✅ Sent | ✅ Sent |
Privacy Benefits
- Privacy-conscious users can still use basic features without full tracking
- Different apps can have different privacy requirements based on their functionality
- Compliant with GDPR, CCPA, and other privacy laws
- Automatic consent checking - no manual implementation needed
- GDPR Compliant: Works seamlessly with Shopify's privacy framework
Debug Mode
Enable debug mode to see pixel events in the console during development:
// Basic configuration with debug
const glood = createGlood({
apiKey: process.env.GLOOD_API_KEY!,
myShopifyDomain: 'your-store.myshopify.com',
debug: process.env.NODE_ENV === 'development', // Enable in development
});
// Advanced configuration with debug
const glood = createGlood({
apiKey: process.env.GLOOD_API_KEY!,
myShopifyDomain: 'your-store.myshopify.com',
apps: { /* ... */ },
debug: true, // Always enabled
});When debug mode is enabled, you'll see console logs like:
[Glood Debug] Product viewed: { productId: '123', productTitle: 'Cool T-Shirt', ... }
[Glood Debug] Sending pixel event to: https://events.glood.aiAPI Reference
Core Functions
createGlood(config)- Create and configure the Glood clientGloodProvider- React context provider component
App Modules
recommendations()- Enable product recommendations functionalitysearch()- Enable search functionalitywishlist()- Enable wishlist functionality
TypeScript Types
// Basic configuration interface
interface GloodConfig {
apiKey: string;
myShopifyDomain: string;
debug?: boolean;
}
// Advanced configuration interface
interface GloodAdvancedConfig extends GloodConfig {
apps?: {
recommendations?: {
endpoint: string;
pixel: {
enabled: boolean;
endpoint: string;
consent: ConsentType[];
};
};
search?: {
endpoint: string;
pixel: {
enabled: boolean;
endpoint: string;
consent: ConsentType[];
};
};
wishlist?: {
endpoint: string;
pixel: {
enabled: boolean;
endpoint: string;
consent: ConsentType[];
};
};
};
}
// Consent types
type ConsentType = 'analytics' | 'marketing' | 'preferences' | 'sale_of_data';Complete Usage Example
Here's a full working example showing how to integrate Glood into your Hydrogen app:
Environment Setup
# .env
GLOOD_API_KEY=your_actual_glood_api_keyRoot Layout (app/root.tsx)
import {
Links,
Meta,
Outlet,
Scripts,
ScrollRestoration,
} from '@remix-run/react';
import { Analytics } from '@shopify/hydrogen';
import { GloodProvider, createGlood } from '@glood/hydrogen';
import { recommendations } from '@glood/hydrogen/recommendations';
import { search } from '@glood/hydrogen/search';
import { wishlist } from '@glood/hydrogen/wishlist';
import { useLoaderData } from 'react-router';
// Simple Glood configuration - uses default endpoints
const glood = createGlood({
apiKey: process.env.GLOOD_API_KEY!,
myShopifyDomain: 'your-store.myshopify.com', // Replace with your domain
})
.use(recommendations())
.use(search())
.use(wishlist());
export default function App() {
const loaderData = useLoaderData();
return (
<html>
<head>
<meta charSet="utf-8" />
<meta name="viewport" content="width=device-width,initial-scale=1" />
<Meta />
<Links />
</head>
<body>
<Analytics>
<GloodProvider client={glood} loaderData={loaderData}>
<Outlet />
</GloodProvider>
</Analytics>
<ScrollRestoration />
<Scripts />
</body>
</html>
);
}What This Setup Provides
✅ Automatic Event Tracking: All user interactions are tracked automatically ✅ Privacy Compliant: Respects customer consent preferences ✅ Debug Logging: Console logs in development to verify events ✅ Modular Apps: Only enabled apps will receive and process events ✅ TypeScript Support: Full type safety and IntelliSense
Verification
After setup, open your browser's developer console in development mode. You should see:
[Glood Debug] Page viewed: { url: '/products/cool-shirt', title: 'Cool Shirt', ... }
[Glood Debug] Product viewed: { productId: 'gid://shopify/Product/123', ... }Examples
Check out the examples directory for implementation examples:
- Basic Integration - Simple setup with default configuration
- Advanced Configuration - Custom endpoints, selective apps, environment-specific setups
- Custom Consent - Per-app consent requirements for privacy compliance
- TypeScript Definitions - Full type definitions and usage
Development
# Install dependencies
npm install
# Start development server
npm run dev
# Run tests
npm test
# Build for production
npm run build
# Type checking
npm run typecheck
# Linting
npm run lintRequirements
- Node.js 18+
- React 18+
- Shopify Hydrogen 2024.0.0+
Contributing
We welcome contributions! Please see our Contributing Guide for details.
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add some amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
License
This project is licensed under the MIT License - see the LICENSE file for details.
Support
Built with ❤️ by the Glood Team
