Skip to main content
POST
/
public
/
tracking
/
events
curl -X POST "https://your-store.myshopify.com/apps/proxy_genlook-x/public/tracking/events" \
  -H "Content-Type: application/json" \
  -d '{
    "events": [
      {
        "event": "widget:button_click",
        "properties": {
          "product_id": "gid://shopify/Product/456",
          "button_style": "primary"
        },
        "timestamp": "2024-01-15T10:30:00Z",
        "$insert_id": "event_123"
      }
    ],
    "context": {
      "$current_url": "https://yourstore.com/products/tshirt",
      "$pathname": "/products/tshirt",
      "$host": "yourstore.com",
      "$referrer": "https://google.com",
      "$referring_domain": "google.com",
      "$screen_width": 1920,
      "$screen_height": 1080,
      "$viewport_width": 1440,
      "$viewport_height": 900,
      "$raw_user_agent": "Mozilla/5.0...",
      "$browser_language": "en-US",
      "$timezone": "America/New_York",
      "$session_id": "session_abc123",
      "$pageview_id": "pageview_xyz789",
      "genlook_client_id": "550e8400-e29b-41d4-a716-446655440000",
      "genlook_widget_enabled": true,
      "genlook_product_id": "gid://shopify/Product/456",
      "genlook_variant_id": "gid://shopify/ProductVariant/789",
      "genlook_lib_version": "1.0.0"
    }
  }'
{
  "success": true
}
Send batched analytics events to track widget usage, user interactions, and conversion funnels. This endpoint supports auto-batching and is designed for high-volume event tracking.

Request

events
array
required
Array of event objects (1-50 events per batch). Each event contains:
  • event (string, required): Event type name (see Event Types below)
  • properties (object, optional): Additional event properties
  • timestamp (string, required): ISO 8601 timestamp
  • $insert_id (string, required): Unique event ID for deduplication
context
object
required
Shared context applied to all events in the batch. Includes page context, device info, session data, and Genlook-specific fields. See Context Fields below.
curl -X POST "https://your-store.myshopify.com/apps/proxy_genlook-x/public/tracking/events" \
  -H "Content-Type: application/json" \
  -d '{
    "events": [
      {
        "event": "widget:button_click",
        "properties": {
          "product_id": "gid://shopify/Product/456",
          "button_style": "primary"
        },
        "timestamp": "2024-01-15T10:30:00Z",
        "$insert_id": "event_123"
      }
    ],
    "context": {
      "$current_url": "https://yourstore.com/products/tshirt",
      "$pathname": "/products/tshirt",
      "$host": "yourstore.com",
      "$referrer": "https://google.com",
      "$referring_domain": "google.com",
      "$screen_width": 1920,
      "$screen_height": 1080,
      "$viewport_width": 1440,
      "$viewport_height": 900,
      "$raw_user_agent": "Mozilla/5.0...",
      "$browser_language": "en-US",
      "$timezone": "America/New_York",
      "$session_id": "session_abc123",
      "$pageview_id": "pageview_xyz789",
      "genlook_client_id": "550e8400-e29b-41d4-a716-446655440000",
      "genlook_widget_enabled": true,
      "genlook_product_id": "gid://shopify/Product/456",
      "genlook_variant_id": "gid://shopify/ProductVariant/789",
      "genlook_lib_version": "1.0.0"
    }
  }'

Event Types

Common event types you can track:
Event TypeDescription
product_page:page_viewProduct page viewed
product_page:cart_addItem added to cart from product page
widget:button_viewWidget button displayed
widget:button_clickWidget button clicked
widget:modal_closeWidget modal closed
widget:image_uploadUser uploaded an image
widget:image_upload_successImage upload succeeded
widget:image_upload_errorImage upload failed
widget:generation_startGeneration job started
widget:result_viewGeneration result displayed
widget:product_clickUser clicked product link from result
widget:email_prompt_viewEmail collection prompt shown
widget:email_collectedEmail successfully collected
widget:share_clickedShare button clicked
widget:download_clickedDownload button clicked
widget:add_to_cart_clickedAdd to cart clicked from widget
widget:add_to_cart_successAdd to cart succeeded
widget:add_to_cart_errorAdd to cart failed
order:createdOrder created (via webhook)
api:errorAPI error occurred
Event type names follow the format category:object_action (e.g., widget:button_click). Use lowercase with snake_case.

Context Fields

Shared context fields applied to all events in a batch:

Page Context

  • $current_url - Full current page URL
  • $pathname - URL pathname
  • $host - Domain/hostname
  • $referrer - Referrer URL (or null)
  • $referring_domain - Referrer domain (or null)

Screen & Viewport

  • $screen_width - Screen width in pixels
  • $screen_height - Screen height in pixels
  • $viewport_width - Viewport width in pixels
  • $viewport_height - Viewport height in pixels

Device

  • $raw_user_agent - Full user agent string

Locale

  • $browser_language - Browser language (e.g., “en-US”)
  • $timezone - Timezone (e.g., “America/New_York”)

Session

  • $session_id - Unique session identifier
  • $pageview_id - Unique pageview identifier

Genlook-Specific

  • genlook_client_id - UUID client identifier
  • genlook_widget_enabled - Whether widget is enabled
  • genlook_product_id - Current product ID (or null)
  • genlook_variant_id - Current variant ID (or null)
  • genlook_lib_version - Widget library version

Response

success
boolean
required
Whether the batch was processed successfully.
message
string
Optional message describing the result or any errors.
{
  "success": true
}

Batching Best Practices

Batch events: Send multiple events in a single batch to reduce API calls. Maximum 50 events per batch.
Auto-batching: Implement client-side batching that collects events and sends them periodically (e.g., every 5 seconds or when batch reaches 20 events).
Deduplication: Use unique $insert_id values for each event to prevent duplicate tracking if requests are retried.

Example: Auto-Batching Implementation

class EventTracker {
  constructor() {
    this.events = [];
    this.context = this.buildContext();
    this.batchInterval = 5000; // 5 seconds
    this.maxBatchSize = 20;
    this.startBatching();
  }
  
  buildContext() {
    return {
      $current_url: window.location.href,
      $pathname: window.location.pathname,
      $host: window.location.host,
      $referrer: document.referrer || null,
      $referring_domain: document.referrer ? new URL(document.referrer).hostname : null,
      $screen_width: screen.width,
      $screen_height: screen.height,
      $viewport_width: window.innerWidth,
      $viewport_height: window.innerHeight,
      $raw_user_agent: navigator.userAgent,
      $browser_language: navigator.language,
      $timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
      $session_id: this.getSessionId(),
      $pageview_id: this.getPageviewId(),
      genlook_client_id: this.getClientId(),
      genlook_widget_enabled: true,
      genlook_product_id: this.getProductId(),
      genlook_variant_id: this.getVariantId(),
      genlook_lib_version: '1.0.0'
    };
  }
  
  track(event, properties = {}) {
    this.events.push({
      event,
      properties,
      timestamp: new Date().toISOString(),
      $insert_id: `event_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`
    });
    
    // Send immediately if batch is full
    if (this.events.length >= this.maxBatchSize) {
      this.flush();
    }
  }
  
  async flush() {
    if (this.events.length === 0) return;
    
    const eventsToSend = [...this.events];
    this.events = [];
    
    try {
      await fetch('/apps/proxy_genlook-x/public/tracking/events', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          events: eventsToSend,
          context: this.buildContext() // Refresh context
        })
      });
    } catch (error) {
      console.error('Failed to track events:', error);
      // Optionally re-queue events for retry
    }
  }
  
  startBatching() {
    setInterval(() => this.flush(), this.batchInterval);
    // Also flush on page unload
    window.addEventListener('beforeunload', () => this.flush());
  }
  
  getSessionId() {
    let sessionId = sessionStorage.getItem('genlook_session_id');
    if (!sessionId) {
      sessionId = `session_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
      sessionStorage.setItem('genlook_session_id', sessionId);
    }
    return sessionId;
  }
  
  getPageviewId() {
    return `pageview_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
  }
  
  getClientId() {
    let clientId = localStorage.getItem('genlook_client_id');
    if (!clientId) {
      clientId = crypto.randomUUID();
      localStorage.setItem('genlook_client_id', clientId);
    }
    return clientId;
  }
  
  getProductId() {
    // Extract from page or context
    return window.Shopify?.product?.id ? `gid://shopify/Product/${window.Shopify.product.id}` : null;
  }
  
  getVariantId() {
    // Extract from page or context
    return window.Shopify?.product?.selected_or_first_available_variant?.id 
      ? `gid://shopify/ProductVariant/${window.Shopify.product.selected_or_first_available_variant.id}` 
      : null;
  }
}

// Usage
const tracker = new EventTracker();
tracker.track('widget:button_click', { button_style: 'primary' });
tracker.track('widget:image_upload', { file_size: 1024000 });

Error Handling

Tracking failures should not block user flow. Always catch errors and continue execution. Failed events can be queued for retry.
The endpoint uses a “fail gracefully” approach. Even if tracking fails, it returns success to avoid blocking your application. Errors are logged server-side for debugging.
{
  "success": false,
  "message": "Invalid event format"
}

Analytics Use Cases

Track these key funnels:
  1. Widget Engagement: widget:button_viewwidget:button_clickwidget:image_upload
  2. Generation Flow: widget:generation_startwidget:result_viewwidget:product_click
  3. Conversion: widget:add_to_cart_clickedwidget:add_to_cart_successorder:created
  4. Email Collection: widget:email_prompt_viewwidget:email_collected
Events are processed by PostHog and can be used to build dashboards, funnels, and conversion reports in the Genlook admin panel.