API ReferenceAnalytics API

Analytics API Reference

Complete reference for the Patchwork Analytics API available in your components.

Getting Started

Access the analytics instance from your embedded component:

const component = document.querySelector("tapestry-component");
const analytics = component.getAnalytics();

Or from inside your component’s JavaScript code:

export async function mount(analytics, shadowRoot) {
  // analytics is already available here
  analytics.sendEvent("component_ready");
}

API Methods

sendEvent()

Track custom user interactions and events.

Signature:

sendEvent(eventName: string, eventData: Record<string, any>): void

Parameters:

ParameterTypeDescription
eventNamestringName of the event (e.g., “button_click”)
eventDataRecord<string, any>Additional data about the event

Returns: void

Example - Button Click:

analytics.sendEvent("button_click", {
  button_id: "signup",
  location: "header",
  color: "primary",
});

Example - Product View:

analytics.sendEvent("product_view", {
  product_id: "prod_123",
  product_name: "Premium Plan",
  price: 49.99,
  currency: "USD",
});

Example - Custom Interaction:

analytics.sendEvent("video_play", {
  video_id: "intro_video",
  duration: 120,
  autoplay: false,
});

submitData()

Track form submissions and data collection. This method attempts to send data immediately.

Signature:

submitData(formData: Record<string, any>): Promise<boolean>

Parameters:

ParameterTypeDescription
formDataRecord<string, any>Form data to track and submit

Returns: Promise<boolean> - true if successfully sent, false if queued for later

Example - Contact Form:

const form = shadowRoot.querySelector("form");
 
form.addEventListener("submit", async (e) => {
  e.preventDefault();
 
  const success = await analytics.submitData({
    email: form.email.value,
    name: form.name.value,
    message: form.message.value,
    timestamp: new Date().toISOString(),
  });
 
  if (success) {
    console.log("Form data tracked successfully");
  }
});

Example - Newsletter Signup:

await analytics.submitData({
  email: "user@example.com",
  source: "homepage_banner",
  preferences: ["product_updates", "newsletter"],
});

Example - Lead Capture:

const success = await analytics.submitData({
  company: "Acme Corp",
  email: "contact@acme.com",
  plan_interest: "enterprise",
  employee_count: "50-100",
});
 
if (success) {
  // Show success message
}

Event Data Best Practices

Use Descriptive Event Names

// Good
analytics.sendEvent("checkout_started");
analytics.sendEvent("add_to_cart");
analytics.sendEvent("filter_applied");
 
// Avoid
analytics.sendEvent("click");
analytics.sendEvent("event1");

Include Relevant Context

// Good - includes context
analytics.sendEvent("search_performed", {
  query: "pricing plans",
  results_count: 12,
  filter: "all_products",
  search_source: "navbar",
});
 
// Missing useful context
analytics.sendEvent("search_performed", {
  query: "pricing plans",
});

Keep Data Structures Simple

// Good - flat structure
analytics.sendEvent("item_selected", {
  item_id: "123",
  item_name: "Widget",
  category: "gadgets",
  price: 29.99,
});
 
// Works but less ideal - nested objects are supported
analytics.sendEvent("item_selected", {
  item: {
    id: "123",
    details: {
      name: "Widget",
      pricing: { amount: 29.99 },
    },
  },
});

Common Use Cases

Tracking Button Clicks

shadowRoot.querySelectorAll("button").forEach((button) => {
  button.addEventListener("click", (e) => {
    analytics.sendEvent("button_click", {
      button_text: e.target.textContent,
      button_id: e.target.id,
      timestamp: Date.now(),
    });
  });
});

Tracking Form Interactions

// Track when user starts filling form
form.addEventListener(
  "focus",
  () => {
    analytics.sendEvent("form_started", {
      form_id: "contact_form",
    });
  },
  true
);
 
// Track submission
form.addEventListener("submit", async (e) => {
  e.preventDefault();
 
  await analytics.submitData({
    email: form.email.value,
    plan: form.plan.value,
  });
});

Tracking Navigation

shadowRoot.querySelectorAll("a").forEach((link) => {
  link.addEventListener("click", (e) => {
    analytics.sendEvent("link_click", {
      href: link.href,
      text: link.textContent,
      external: !link.href.startsWith(window.location.origin),
    });
  });
});

Tracking Time on Page

const startTime = Date.now();
 
window.addEventListener("beforeunload", () => {
  analytics.sendEvent("time_on_page", {
    duration_seconds: (Date.now() - startTime) / 1000,
    page_url: window.location.href,
  });
});

Automatic Metadata

All events automatically include metadata you don’t need to provide:

  • Session ID - Unique session identifier
  • Timestamp - ISO 8601 timestamp
  • Component Info - Component ID, name, and version
  • Organization ID - Your organization identifier
  • Browser Info - User agent string
  • Page Context - Current URL and referrer
  • Event ID - Unique event identifier

Notes

  • Events are automatically batched and sent efficiently
  • sendEvent() is fire-and-forget (non-blocking)
  • submitData() attempts immediate delivery and returns a Promise
  • Data is automatically sanitized (functions and symbols are removed)
  • No PII (Personally Identifiable Information) should be tracked without user consent

Next Steps

2026 © Patchwork. All rights reserved.