> ## Documentation Index
> Fetch the complete documentation index at: https://docs.glood.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Utilities

> Utility functions for consent management, constants, data transformation, and browser context

# Utilities

The SDK provides various utility functions for consent management, data transformation, browser context handling, and other common operations.

## Consent Management

### checkConsent()

Checks if all required consent types have been granted by the customer.

```typescript theme={null}
function checkConsent(
  requiredConsents: ConsentType[],
  canTrack: any,
  analytics: any
): boolean
```

**Parameters:**

* `requiredConsents` - Array of consent types that must be granted
* `canTrack` - Hydrogen's canTrack function from analytics
* `analytics` - Hydrogen's analytics instance

**Returns:** `true` if all required consents are granted, `false` otherwise

**Usage:**

```typescript theme={null}
import { checkConsent, CONSENT_TYPES } from '@glood/hydrogen';

// Check if analytics consent is granted
const canSendAnalytics = checkConsent(
  [CONSENT_TYPES.ANALYTICS],
  canTrack,
  analytics
);

// Check multiple consent types
const canSendMarketing = checkConsent(
  [CONSENT_TYPES.ANALYTICS, CONSENT_TYPES.MARKETING],
  canTrack,
  analytics
);

if (canSendAnalytics) {
  // Send analytics pixel
}
```

**Implementation Details:**

```typescript theme={null}
export function checkConsent(
  requiredConsents: ConsentType[],
  canTrack: any,
  analytics: any
): boolean {
  if (!requiredConsents || requiredConsents.length === 0) {
    return true; // No consent required
  }

  return requiredConsents.every(consentType => {
    switch (consentType) {
      case 'analytics':
        return analytics.customerPrivacy?.analyticsProcessingAllowed();
      case 'marketing':
        return analytics.customerPrivacy?.marketingAllowed();
      case 'preferences':
        return analytics.customerPrivacy?.preferencesProcessingAllowed();
      case 'sale_of_data':
        return analytics.customerPrivacy?.saleOfDataAllowed();
      default:
        return false;
    }
  });
}
```

## Constants

### DEFAULT\_ENDPOINTS

Default API and pixel endpoints for all apps.

```typescript theme={null}
const DEFAULT_ENDPOINTS = {
  recommendations: {
    main: 'https://storefront.glood.ai',
    pixel: 'https://events.glood.ai',
  },
  search: {
    main: 'https://s-s.glood.ai',
    pixel: 'https://s-pixel.glood.ai',
  },
  wishlist: {
    main: 'https://w-s.glood.ai',
    pixel: 'https://w-pixel.glood.ai',
  },
} as const;
```

**Usage:**

```typescript theme={null}
import { DEFAULT_ENDPOINTS } from '@glood/hydrogen';

// Get recommendations endpoints
const recEndpoint = DEFAULT_ENDPOINTS.recommendations.main;
const recPixel = DEFAULT_ENDPOINTS.recommendations.pixel;

// Use in custom configuration
const customConfig = {
  endpoint: DEFAULT_ENDPOINTS.search.main,
  pixel: {
    enabled: true,
    endpoint: DEFAULT_ENDPOINTS.search.pixel,
    consent: ['analytics'],
  },
};
```

### DEFAULT\_PIXEL\_CONFIG

Default pixel configuration settings.

```typescript theme={null}
const DEFAULT_PIXEL_CONFIG = {
  enabled: true,
} as const;
```

### ALL\_EVENTS

Array of all supported event types.

```typescript theme={null}
const ALL_EVENTS = [
  'page_viewed',
  'product_viewed',
  'collection_viewed',
  'cart_viewed',
  'search_viewed',
  'search_submitted',
  'custom_promotion_viewed',
  'product_added_to_cart',
  'product_removed_from_cart',
] as const;
```

**Usage:**

```typescript theme={null}
import { ALL_EVENTS } from '@glood/hydrogen';

// Check if event type is valid
function isValidEventType(eventType: string): boolean {
  return ALL_EVENTS.includes(eventType as any);
}

// Get all event types
const eventTypes = [...ALL_EVENTS];
```

### CONSENT\_TYPES

Constants for all consent types.

```typescript theme={null}
const CONSENT_TYPES = {
  ANALYTICS: 'analytics',
  MARKETING: 'marketing',
  PREFERENCES: 'preferences',
  SALE_OF_DATA: 'sale_of_data',
} as const;
```

**Usage:**

```typescript theme={null}
import { CONSENT_TYPES } from '@glood/hydrogen';

// Use in configuration
const pixelConfig = {
  enabled: true,
  endpoint: 'https://events.glood.ai',
  consent: [CONSENT_TYPES.ANALYTICS, CONSENT_TYPES.MARKETING],
};

// Type-safe consent checking
const requiredConsents = [
  CONSENT_TYPES.ANALYTICS,
  CONSENT_TYPES.PREFERENCES,
];
```

### DEFAULT\_PIXEL\_CONSENT

Default consent requirements for each app.

```typescript theme={null}
const DEFAULT_PIXEL_CONSENT = {
  recommendations: [CONSENT_TYPES.ANALYTICS, CONSENT_TYPES.MARKETING],
  search: [CONSENT_TYPES.ANALYTICS],
  wishlist: [CONSENT_TYPES.ANALYTICS, CONSENT_TYPES.PREFERENCES],
} as const;
```

**Usage:**

```typescript theme={null}
import { DEFAULT_PIXEL_CONSENT } from '@glood/hydrogen';

// Get default consent for an app
const recConsent = DEFAULT_PIXEL_CONSENT.recommendations;
// ['analytics', 'marketing']

// Use in custom configuration
const customSearchConfig = {
  endpoint: 'https://custom-search.glood.ai',
  pixel: {
    enabled: true,
    endpoint: 'https://custom-pixel.glood.ai',
    consent: DEFAULT_PIXEL_CONSENT.search, // ['analytics']
  },
};
```

## Data Transformers

### transformCartData()

Transforms Shopify cart data to Glood pixel format.

```typescript theme={null}
function transformCartData(shopifyCart: any): any
```

**Parameters:**

* `shopifyCart` - Shopify cart object from analytics events

**Returns:** Transformed cart data in Glood format, or `null` if cart is empty

**Usage:**

```typescript theme={null}
import { transformCartData } from '@glood/hydrogen';

// Transform cart from Shopify analytics event
const transformedCart = transformCartData(eventData.cart);

if (transformedCart) {
  console.log('Cart total:', transformedCart.cost.totalAmount.amount);
  console.log('Item count:', transformedCart.totalQuantity);
}
```

**Transformation Example:**

```typescript theme={null}
// Input: Shopify cart
{
  id: 'gid://shopify/Cart/abc123?key=def456',
  cost: {
    totalAmount: { amount: '29.99', currencyCode: 'USD' }
  },
  lines: {
    nodes: [{
      cost: { totalAmount: { amount: '29.99', currencyCode: 'USD' } },
      merchandise: {
        id: 'gid://shopify/ProductVariant/123',
        title: 'Blue T-Shirt',
        price: { amount: '29.99', currencyCode: 'USD' },
        product: {
          id: 'gid://shopify/Product/456',
          title: 'Cool T-Shirt',
          handle: 'cool-t-shirt'
        }
      },
      quantity: 1
    }]
  },
  totalQuantity: 1
}

// Output: Glood format
{
  id: 'abc123',
  cost: {
    totalAmount: { amount: 29.99, currencyCode: 'USD' }
  },
  lines: [{
    cost: {
      totalAmount: { amount: 29.99, currencyCode: 'USD' }
    },
    merchandise: {
      id: '123',
      title: 'Blue T-Shirt',
      price: { amount: 29.99, currencyCode: 'USD' },
      product: {
        id: '456',
        title: 'Cool T-Shirt',
        url: '/products/cool-t-shirt',
        // ... other fields
      }
    },
    quantity: 1
  }],
  totalQuantity: 1
}
```

### transformShopData()

Transforms shop data to Glood pixel format.

```typescript theme={null}
function transformShopData(shopData: any, myShopifyDomain: string): any
```

**Parameters:**

* `shopData` - Shop data from analytics events
* `myShopifyDomain` - Your Shopify domain

**Returns:** Transformed shop data in Glood format

**Usage:**

```typescript theme={null}
import { transformShopData } from '@glood/hydrogen';

const transformedShop = transformShopData(
  eventData.shop,
  'my-store.myshopify.com'
);

console.log('Shop name:', transformedShop.name);
console.log('Currency:', transformedShop.paymentSettings.currencyCode);
```

### createCustomerPrivacy()

Creates customer privacy object from analytics data.

```typescript theme={null}
function createCustomerPrivacy(analytics: any): any
```

**Parameters:**

* `analytics` - Hydrogen analytics instance

**Returns:** Customer privacy object with consent status

**Usage:**

```typescript theme={null}
import { createCustomerPrivacy } from '@glood/hydrogen';

const customerPrivacy = createCustomerPrivacy(analytics);

console.log('Analytics allowed:', customerPrivacy.analyticsProcessingAllowed);
console.log('Marketing allowed:', customerPrivacy.marketingAllowed);
```

**Output Example:**

```typescript theme={null}
{
  analyticsProcessingAllowed: true,
  marketingAllowed: false,
  preferencesProcessingAllowed: true,
  saleOfDataAllowed: false,
}
```

### getPageTitle()

Gets the current page title with fallback.

```typescript theme={null}
function getPageTitle(fallback: string = ''): string
```

**Parameters:**

* `fallback` - Fallback title if document.title is not available

**Returns:** Current page title or fallback

**Usage:**

```typescript theme={null}
import { getPageTitle } from '@glood/hydrogen';

const title = getPageTitle('Default Title');
console.log('Page title:', title);
```

### getCurrentUrl()

Gets the current URL from window or event data.

```typescript theme={null}
function getCurrentUrl(eventData?: any): string
```

**Parameters:**

* `eventData` - Optional event data that might contain URL

**Returns:** Current URL string

**Usage:**

```typescript theme={null}
import { getCurrentUrl } from '@glood/hydrogen';

const url = getCurrentUrl(eventData);
console.log('Current URL:', url);
```

## ID Generators

### generateEventId()

Generates a unique event ID.

```typescript theme={null}
function generateEventId(): string
```

**Returns:** Unique event ID string

**Usage:**

```typescript theme={null}
import { generateEventId } from '@glood/hydrogen';

const eventId = generateEventId();
console.log('Event ID:', eventId); // "evt_abc123def456"
```

### CookieStorage

Utility class for managing client IDs and session data.

#### getOrGenerateClientId()

Gets or generates a persistent client ID.

```typescript theme={null}
static getOrGenerateClientId(): string
```

**Returns:** Client ID string (persistent across browser sessions)

#### getOrGenerateSessionId()

Gets or generates a session ID.

```typescript theme={null}
static getOrGenerateSessionId(): string
```

**Returns:** Session ID string (valid for current browser session)

#### getOrGenerateRkUid()

Gets or generates a user ID for analytics.

```typescript theme={null}
static getOrGenerateRkUid(analytics: any): string
```

**Parameters:**

* `analytics` - Hydrogen analytics instance

**Returns:** User ID string (prefers analytics customer ID, falls back to client ID)

**Usage:**

```typescript theme={null}
import { CookieStorage } from '@glood/hydrogen';

// Get persistent client ID
const clientId = CookieStorage.getOrGenerateClientId();

// Get session ID
const sessionId = CookieStorage.getOrGenerateSessionId();

// Get user ID for analytics
const userId = CookieStorage.getOrGenerateRkUid(analytics);
```

### extractCartIdentifier()

Extracts cart identifier from Shopify cart data.

```typescript theme={null}
function extractCartIdentifier(cart: any): string | null
```

**Parameters:**

* `cart` - Shopify cart object

**Returns:** Cart identifier string or `null` if not available

**Usage:**

```typescript theme={null}
import { extractCartIdentifier } from '@glood/hydrogen';

const cartId = extractCartIdentifier(eventData.cart);
if (cartId) {
  console.log('Cart identifier:', cartId);
}
```

## Browser Context

### browserContext

Utility object for getting browser environment information.

#### getContext()

Gets comprehensive browser context information.

```typescript theme={null}
getContext(): BrowserContext
```

**Returns:** Browser context object with page, user agent, screen, and locale information

**Usage:**

```typescript theme={null}
import { browserContext } from '@glood/hydrogen';

const context = browserContext.getContext();

console.log('Page URL:', context.page.url);
console.log('Screen size:', context.screen.width, 'x', context.screen.height);
console.log('Language:', context.language);
console.log('Timezone:', context.timezone);
```

**Output Example:**

```typescript theme={null}
{
  page: {
    url: 'https://store.myshopify.com/products/shirt',
    title: 'Cool Shirt - My Store',
    referrer: 'https://google.com'
  },
  userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
  screen: {
    width: 1920,
    height: 1080
  },
  language: 'en-US',
  timezone: 'America/New_York'
}
```

## Pixel Queue

### getPixelQueue()

Gets the global pixel queue instance for sending events.

```typescript theme={null}
function getPixelQueue(debug?: boolean): PixelQueue
```

**Parameters:**

* `debug` - Enable debug logging for pixel transmission

**Returns:** PixelQueue instance

**Usage:**

```typescript theme={null}
import { getPixelQueue } from '@glood/hydrogen';

const pixelQueue = getPixelQueue(true); // Enable debug mode

// Send a pixel event
pixelQueue.add({
  endpoint: 'https://events.glood.ai',
  data: {
    event: {
      id: 'evt_123',
      name: 'product_viewed',
      // ... event data
    }
  }
});
```

### resetPixelQueue()

Resets the pixel queue (mainly for testing).

```typescript theme={null}
function resetPixelQueue(): void
```

**Usage:**

```typescript theme={null}
import { resetPixelQueue } from '@glood/hydrogen';

// Reset queue (typically used in tests)
resetPixelQueue();
```

## Advanced Usage Examples

### Custom Consent Checker

```typescript theme={null}
import { checkConsent, CONSENT_TYPES } from '@glood/hydrogen';

function createCustomConsentChecker(analytics: any) {
  return {
    canSendAnalytics: () => checkConsent([CONSENT_TYPES.ANALYTICS], null, analytics),
    canSendMarketing: () => checkConsent([CONSENT_TYPES.MARKETING], null, analytics),
    canPersonalize: () => checkConsent([CONSENT_TYPES.PREFERENCES], null, analytics),
    canSellData: () => checkConsent([CONSENT_TYPES.SALE_OF_DATA], null, analytics),

    // Custom combination checks
    canSendRecommendations: () => checkConsent(
      [CONSENT_TYPES.ANALYTICS, CONSENT_TYPES.MARKETING],
      null,
      analytics
    ),

    canTrackWishlist: () => checkConsent(
      [CONSENT_TYPES.ANALYTICS, CONSENT_TYPES.PREFERENCES],
      null,
      analytics
    ),
  };
}

// Usage
const consentChecker = createCustomConsentChecker(analytics);

if (consentChecker.canSendRecommendations()) {
  // Send recommendations pixel
}
```

### Custom Event Transformer

```typescript theme={null}
import {
  transformCartData,
  transformShopData,
  generateEventId,
  CookieStorage,
  browserContext
} from '@glood/hydrogen';

function createCustomEventTransformer(client: GloodClient) {
  return {
    transformEvent(eventType: string, eventData: any) {
      const baseEvent = {
        id: generateEventId(),
        name: eventType,
        type: 'custom',
        timestamp: new Date().toISOString(),
        clientId: CookieStorage.getOrGenerateClientId(),
        context: browserContext.getContext(),
      };

      const transformedData = {
        customer: eventData.customer || null,
        cart: eventData.cart ? transformCartData(eventData.cart) : null,
        shop: transformShopData(eventData.shop, client.config.myShopifyDomain),
      };

      return {
        event: baseEvent,
        data: transformedData,
        sessionId: CookieStorage.getOrGenerateSessionId(),
        // Add custom fields
        customMetadata: {
          source: 'custom-transformer',
          version: '1.0.0',
        },
      };
    }
  };
}
```

### Environment-Specific Constants

```typescript theme={null}
import { DEFAULT_ENDPOINTS, CONSENT_TYPES } from '@glood/hydrogen';

function getEnvironmentConfig(env: string) {
  const baseConfig = {
    consent: {
      minimal: [CONSENT_TYPES.ANALYTICS],
      standard: [CONSENT_TYPES.ANALYTICS, CONSENT_TYPES.MARKETING],
      full: [CONSENT_TYPES.ANALYTICS, CONSENT_TYPES.MARKETING, CONSENT_TYPES.PREFERENCES],
    },
  };

  switch (env) {
    case 'development':
      return {
        ...baseConfig,
        endpoints: {
          recommendations: {
            main: 'https://dev-storefront.glood.ai',
            pixel: 'https://dev-events.glood.ai',
          },
          // ... other dev endpoints
        },
        pixelEnabled: false, // Disable pixels in dev
      };

    case 'staging':
      return {
        ...baseConfig,
        endpoints: {
          recommendations: {
            main: 'https://staging-storefront.glood.ai',
            pixel: 'https://staging-events.glood.ai',
          },
          // ... other staging endpoints
        },
        pixelEnabled: true,
      };

    case 'production':
    default:
      return {
        ...baseConfig,
        endpoints: DEFAULT_ENDPOINTS,
        pixelEnabled: true,
      };
  }
}
```

## Error Handling Utilities

### Safe Transformation

```typescript theme={null}
import { transformCartData, transformShopData } from '@glood/hydrogen';

function safeTransform<T>(
  transformer: (data: any) => T,
  data: any,
  fallback: T
): T {
  try {
    return transformer(data);
  } catch (error) {
    console.warn('Transform error:', error);
    return fallback;
  }
}

// Usage
const safeCart = safeTransform(transformCartData, eventData.cart, null);
const safeShop = safeTransform(
  (shop) => transformShopData(shop, 'my-store.myshopify.com'),
  eventData.shop,
  { name: 'Unknown Store' }
);
```

### Consent Validation

```typescript theme={null}
import { checkConsent, CONSENT_TYPES } from '@glood/hydrogen';

function validateConsent(
  requiredConsents: ConsentType[],
  analytics: any
): { valid: boolean; missing: ConsentType[] } {
  const missing: ConsentType[] = [];

  for (const consentType of requiredConsents) {
    if (!checkConsent([consentType], null, analytics)) {
      missing.push(consentType);
    }
  }

  return {
    valid: missing.length === 0,
    missing,
  };
}

// Usage
const validation = validateConsent(
  [CONSENT_TYPES.ANALYTICS, CONSENT_TYPES.MARKETING],
  analytics
);

if (!validation.valid) {
  console.log('Missing consents:', validation.missing);
}
```

## Performance Utilities

### Debounced Event Sending

```typescript theme={null}
import { getPixelQueue } from '@glood/hydrogen';

function createDebouncedPixelSender(delay: number = 100) {
  let timeoutId: NodeJS.Timeout;
  const queue: Array<{ endpoint: string; data: any }> = [];

  return {
    add(endpoint: string, data: any) {
      queue.push({ endpoint, data });

      clearTimeout(timeoutId);
      timeoutId = setTimeout(() => {
        const pixelQueue = getPixelQueue();
        queue.forEach(item => pixelQueue.add(item));
        queue.length = 0; // Clear queue
      }, delay);
    }
  };
}
```

## Testing Utilities

### Mock Analytics

```typescript theme={null}
function createMockAnalytics(consents: Partial<Record<ConsentType, boolean>> = {}) {
  return {
    customerPrivacy: {
      analyticsProcessingAllowed: () => consents.analytics ?? true,
      marketingAllowed: () => consents.marketing ?? false,
      preferencesProcessingAllowed: () => consents.preferences ?? false,
      saleOfDataAllowed: () => consents.sale_of_data ?? false,
    },
    subscribe: jest.fn(),
    canTrack: jest.fn(() => true),
  };
}

// Usage in tests
const mockAnalytics = createMockAnalytics({
  analytics: true,
  marketing: false,
});

const canSend = checkConsent([CONSENT_TYPES.ANALYTICS], null, mockAnalytics);
expect(canSend).toBe(true);
```

## See Also

* [Event System](/for-developers/glood-hydrogen-sdk/api-reference/event-system) - How utilities are used in event processing
* [Types Reference](/for-developers/glood-hydrogen-sdk/api-reference/types) - TypeScript types for utilities
* [App Modules](/for-developers/glood-hydrogen-sdk/api-reference/app-modules) - How apps use these utilities
* [Components](/for-developers/glood-hydrogen-sdk/api-reference/components) - React components using utilities
