Skip to main content

Installation Guide

Complete guide to installing and setting up the Glood Hydrogen SDK in your Shopify Hydrogen project.

Prerequisites

Before installing the Glood SDK, ensure you have:
  • Node.js 18+ - Required for Hydrogen projects
  • React 18+ - Hydrogen uses React 18 features
  • Shopify Hydrogen 2024.10.1+ - Compatible Hydrogen version
  • TypeScript 5.4+ - Recommended for full type safety
  • Glood API Key - Contact Glood team to obtain your API key

Step 1: Install the Package

Install the Glood Hydrogen SDK using your preferred package manager:

npm

npm install @glood/hydrogen

yarn

yarn add @glood/hydrogen

pnpm

pnpm add @glood/hydrogen

Step 2: Environment Configuration

Add your Glood API key to your environment variables:

.env file

# .env
GLOOD_API_KEY=your_glood_api_key_here

Environment Variables

Set up environment variables for different environments:
# .env.development
GLOOD_API_KEY=dev_api_key_here
NODE_ENV=development

# .env.staging
GLOOD_API_KEY=staging_api_key_here
NODE_ENV=staging

# .env.production
GLOOD_API_KEY=production_api_key_here
NODE_ENV=production

TypeScript Environment Types

Add environment types for TypeScript projects:
// types/env.d.ts
declare global {
  namespace NodeJS {
    interface ProcessEnv {
      GLOOD_API_KEY: string;
      PUBLIC_STORE_DOMAIN: string;
      PUBLIC_CHECKOUT_DOMAIN: string;
      NODE_ENV: 'development' | 'production' | 'staging';
    }
  }
}

export {};

Step 3: Configure Content Security Policy

Add Glood domains to your CSP configuration to enable pixel tracking:
// app/root.tsx
import { createContentSecurityPolicy } from '@shopify/hydrogen';

export async function loader({context}: LoaderFunctionArgs) {
  const {nonce, header} = createContentSecurityPolicy({
    shop: {
      checkoutDomain: context.env.PUBLIC_CHECKOUT_DOMAIN,
      storeDomain: context.env.PUBLIC_STORE_DOMAIN,
    },
    connectSrc: [
      'https://cdn.shopify.com',
      'https://*.shopifycloud.com',
      // Add Glood pixel endpoints
      'https://events.glood.ai',
      'https://s-pixel.glood.ai',
      'https://w-pixel.glood.ai'
    ],
  });

  return json({ nonce, header });
}

export function headers({loaderHeaders}: {loaderHeaders: Headers}) {
  return {
    'Content-Security-Policy': loaderHeaders.get('Content-Security-Policy'),
  };
}

Step 4: Initialize Glood Client

Create and configure the Glood client in your root layout:

Basic Setup

// app/root.tsx
import { Analytics } from '@shopify/hydrogen';
import { GloodProvider, createGlood } from '@glood/hydrogen';
import { recommendations, search, wishlist } from '@glood/hydrogen';
import { useLoaderData } from 'react-router';

// Create Glood client outside component to prevent recreation
const glood = createGlood({
  apiKey: process.env.GLOOD_API_KEY!,
  myShopifyDomain: 'your-store.myshopify.com', // Replace with your actual domain
})
  .use(recommendations())
  .use(search())
  .use(wishlist());

export default function App() {
  const loaderData = useLoaderData();

  return (
    <html>
      <head>
        <Meta />
        <Links />
      </head>
      <body>
        <Analytics>
          <GloodProvider client={glood} loaderData={loaderData}>
            <Layout>
              <Outlet />
            </Layout>
          </GloodProvider>
        </Analytics>
        <Scripts />
      </body>
    </html>
  );
}

Environment-Specific Setup

// app/root.tsx
import { createGlood } from '@glood/hydrogen';
import { recommendations, search, wishlist } from '@glood/hydrogen';

// Environment-aware configuration
const isDevelopment = process.env.NODE_ENV === 'development';
const isStaging = process.env.NODE_ENV === 'staging';

const glood = createGlood({
  apiKey: process.env.GLOOD_API_KEY!,
  myShopifyDomain: process.env.PUBLIC_STORE_DOMAIN!,
  debug: isDevelopment, // Enable debug logging in development
  apps: isDevelopment ? {
    // Disable pixels in development
    recommendations: {
      endpoint: 'https://storefront.glood.ai',
      pixel: { enabled: false, endpoint: '', consent: [] },
    },
    search: {
      endpoint: 'https://s-s.glood.ai',
      pixel: { enabled: false, endpoint: '', consent: [] },
    },
    wishlist: {
      endpoint: 'https://w-s.glood.ai',
      pixel: { enabled: false, endpoint: '', consent: [] },
    },
  } : undefined, // Use defaults in production
})
  .use(recommendations())
  .use(search())
  .use(wishlist());

Step 5: Verify Installation

Check Debug Logs

Enable debug mode and check browser console:
const glood = createGlood({
  apiKey: process.env.GLOOD_API_KEY!,
  myShopifyDomain: 'your-store.myshopify.com',
  debug: true, // Enable debug logging
});
Expected console output:
[Glood Debug] Setting up event subscriptions for apps: ['recommendations', 'search', 'wishlist']
[Glood Debug] Set analytics instance on recommendations app
[Glood Debug] App recommendations subscribes to events: ['page_viewed', 'product_viewed', ...]
[Glood Debug] All unique event types: ['page_viewed', 'product_viewed', 'search_submitted', ...]

Test Event Tracking

Navigate through your store and verify events are being tracked:
  1. Visit product page - Should see product_viewed events
  2. Search for products - Should see search_submitted events
  3. View cart - Should see cart_viewed events
  4. Navigate pages - Should see page_viewed events

Verify Network Requests

In browser DevTools Network tab, look for requests to:
  • https://events.glood.ai (recommendations pixels)
  • https://s-pixel.glood.ai (search pixels)
  • https://w-pixel.glood.ai (wishlist pixels)

Complete Implementation Example

Here’s a complete working example:
// app/root.tsx
import {
  json,
  type LoaderFunctionArgs,
  type LinksFunction,
  type MetaFunction,
} from '@shopify/remix-oxygen';
import {
  Links,
  Meta,
  Outlet,
  Scripts,
  ScrollRestoration,
  useLoaderData,
} from '@remix-run/react';
import {
  Analytics,
  getShopAnalytics,
  useNonce,
  createContentSecurityPolicy,
} from '@shopify/hydrogen';
import { GloodProvider, createGlood } from '@glood/hydrogen';
import { recommendations, search, wishlist } from '@glood/hydrogen';

import favicon from '../public/favicon.ico';
import resetStyles from './styles/reset.css';
import appStyles from './styles/app.css';

// Create Glood client
const glood = createGlood({
  apiKey: process.env.GLOOD_API_KEY!,
  myShopifyDomain: process.env.PUBLIC_STORE_DOMAIN!,
  debug: process.env.NODE_ENV === 'development',
})
  .use(recommendations())
  .use(search())
  .use(wishlist());

export const links: LinksFunction = () => {
  return [
    {rel: 'stylesheet', href: resetStyles},
    {rel: 'stylesheet', href: appStyles},
    {
      rel: 'preconnect',
      href: 'https://cdn.shopify.com',
    },
    {
      rel: 'preconnect',
      href: 'https://shop.app',
    },
    {rel: 'icon', type: 'image/svg+xml', href: favicon},
  ];
};

export const meta: MetaFunction = () => {
  return [{title: 'Hydrogen | Glood Integration'}];
};

export async function loader({context}: LoaderFunctionArgs) {
  const {storefront, session, cart, env} = context;

  // Configure CSP with Glood domains
  const {nonce, header} = createContentSecurityPolicy({
    shop: {
      checkoutDomain: env.PUBLIC_CHECKOUT_DOMAIN,
      storeDomain: env.PUBLIC_STORE_DOMAIN,
    },
    connectSrc: [
      'https://cdn.shopify.com',
      'https://*.shopifycloud.com',
      'https://events.glood.ai',
      'https://s-pixel.glood.ai',
      'https://w-pixel.glood.ai'
    ],
  });

  const analytics = getShopAnalytics({
    storefront,
    publicStorefrontId: env.PUBLIC_STOREFRONT_ID,
  });

  return json(
    {
      analytics,
      nonce,
    },
    {
      headers: {
        'Content-Security-Policy': header,
      },
    }
  );
}

export default function App() {
  const nonce = useNonce();
  const data = useLoaderData<typeof loader>();

  return (
    <html lang="en">
      <head>
        <meta charSet="utf-8" />
        <meta name="viewport" content="width=device-width,initial-scale=1" />
        <Meta />
        <Links />
      </head>
      <body>
        <Analytics analytics={data.analytics}>
          <GloodProvider client={glood} loaderData={data}>
            <Layout>
              <Outlet />
            </Layout>
          </GloodProvider>
        </Analytics>
        <ScrollRestoration nonce={nonce} />
        <Scripts nonce={nonce} />
      </body>
    </html>
  );
}

export function ErrorBoundary() {
  const error = useRouteError();

  if (isRouteErrorResponse(error)) {
    return (
      <div>
        <h1>
          {error.status} {error.statusText}
        </h1>
        <p>{error.data}</p>
      </div>
    );
  } else if (error instanceof Error) {
    return (
      <div>
        <h1>Error</h1>
        <p>{error.message}</p>
        <p>The stack trace is:</p>
        <pre>{error.stack}</pre>
      </div>
    );
  } else {
    return <h1>Unknown Error</h1>;
  }
}

Common Setup Issues

Issue: CSP Violations

Symptoms: Console errors about blocked requests to Glood domains Solution: Ensure all Glood domains are added to connectSrc:
connectSrc: [
  'https://cdn.shopify.com',
  'https://*.shopifycloud.com',
  'https://events.glood.ai',      // Required
  'https://s-pixel.glood.ai',     // Required
  'https://w-pixel.glood.ai'      // Required
],

Issue: Missing API Key

Symptoms: Console error “Glood: apiKey is required” Solution: Verify environment variable is set:
# Check environment variable
echo $GLOOD_API_KEY

# Or in your app
console.log('API Key:', process.env.GLOOD_API_KEY);

Issue: Invalid Shopify Domain

Symptoms: Warning about non-standard domain format Solution: Use your actual Shopify domain:
// ✅ Correct format
myShopifyDomain: 'your-store.myshopify.com'

// ❌ Incorrect formats
myShopifyDomain: 'your-store'
myShopifyDomain: 'https://your-store.myshopify.com'

Issue: Analytics Not Working

Symptoms: No debug logs, no events tracked Solution: Verify Analytics wrapper and loaderData:
// ✅ Correct - GloodProvider inside Analytics with loaderData
function Root() {
  const loaderData = useLoaderData();
  return (
    <Analytics>
      <GloodProvider client={glood} loaderData={loaderData}>
        <App />
      </GloodProvider>
    </Analytics>
  );
}

// ❌ Incorrect - Missing Analytics wrapper and loaderData
<GloodProvider client={glood}>
  <App />
</GloodProvider>

Issue: TypeScript Errors

Symptoms: TypeScript compilation errors Solution: Install type dependencies:
npm install --save-dev @types/react @types/node

Next Steps

After successful installation:
  1. Configure Apps - Customize app settings
  2. Set Up CSP - Detailed CSP configuration
  3. Review Examples - Implementation patterns
  4. Test Integration - Verify everything works

Getting Help

If you encounter issues during installation:

Package Information