agentsclimarketplace

Algolia webhooks events

Skill jeremylongshore/claude-code-plugins-plus-skills/plugins/saas-packs/algolia-pack/skills/algolia-webhooks-events

'Implement Algolia Insights API for click/conversion tracking, search analytics,From its SKILL.md

Install
npx -y skills add jeremylongshore/claude-code-plugins-plus-skills --skill algolia-webhooks-events

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

What its file declares

Copied from the file, not written here

The file declares its own license as MIT. That is the author’s claim about this one file, and it is not the same thing as the license GitHub reports for the repository, which is listed with the other numbers below.

SKILL.md

6.4 KB, ~1.5k tokens by cl100k_base, as published. Nobody here has run it

Algolia Events & Insights

Overview

Algolia doesn't use traditional webhooks. Instead, it provides the Insights API for sending user behavior events (clicks, conversions, views) back to Algolia, and the Analytics API for reading search performance data. For keeping your index in sync, you build event-driven pipelines from your database to Algolia.

Prerequisites

  • algoliasearch v5 installed (Insights client is included)
  • Index with records and queryID enabled (for click analytics)
  • search-insights npm package for frontend event tracking

Instructions

Step 1: Enable Click Analytics in Search

import { algoliasearch } from 'algoliasearch';

const client = algoliasearch(process.env.ALGOLIA_APP_ID!, process.env.ALGOLIA_ADMIN_KEY!);

// Enable clickAnalytics to get queryID in search results
const { hits, queryID } = await client.searchSingleIndex({
  indexName: 'products',
  searchParams: {
    query: 'running shoes',
    clickAnalytics: true,  // Returns queryID for event correlation
  },
});
// queryID links this search to subsequent click/conversion events

Step 2: Send Click and Conversion Events (Backend)

// The Insights API is built into the algoliasearch client
// Events connect user behavior back to specific search queries

// Track a click on a search result
await client.pushEvents({
  events: [{
    eventType: 'click',
    eventName: 'Product Clicked',
    index: 'products',
    userToken: 'user-123',        // Unique user identifier
    queryID: queryID,              // From search response
    objectIDs: ['product-456'],    // What was clicked
    positions: [3],                // Position in results (1-indexed)
    timestamp: Date.now(),
  }],
});

// Track a conversion (purchase, add-to-cart)
await client.pushEvents({
  events: [{
    eventType: 'conversion',
    eventName: 'Product Purchased',
    index: 'products',
    userToken: 'user-123',
    queryID: queryID,
    objectIDs: ['product-456'],
    timestamp: Date.now(),
  }],
});

// Track a view (product page visit, no search context)
await client.pushEvents({
  events: [{
    eventType: 'view',
    eventName: 'Product Viewed',
    index: 'products',
    userToken: 'user-123',
    objectIDs: ['product-456'],
    timestamp: Date.now(),
  }],
});

Step 3: Frontend Event Tracking with search-insights

npm install search-insights
// Frontend: lightweight event tracking
import { default as aa } from 'search-insights';

aa('init', {
  appId: 'YourAppID',
  apiKey: 'YourSearchOnlyKey',  // Search-only key is fine for events
});

// Set user token (anonymous or authenticated)
aa('setUserToken', 'user-123');

// After user clicks a search result
aa('clickedObjectIDsAfterSearch', {
  eventName: 'Product Clicked',
  index: 'products',
  queryID: 'abc123',          // From search response
  objectIDs: ['product-456'],
  positions: [3],
});

// After user converts (purchases)
aa('convertedObjectIDsAfterSearch', {
  eventName: 'Product Purchased',
  index: 'products',
  queryID: 'abc123',
  objectIDs: ['product-456'],
});

Step 4: Read Search Analytics

// The analytics client is part of algoliasearch
const analyticsClient = client.initAnalytics({ region: 'us' });

// Top searches
const { searches } = await client.getTopSearches({
  index: 'products',
  startDate: '2025-01-01',
  endDate: '2025-01-31',
});
searches.forEach(s => console.log(`"${s.search}" — ${s.count} searches, ${s.nbHits} avg hits`));

// Searches with no results (critical for relevance tuning)
const { searches: noResults } = await client.getSearchesNoResults({
  index: 'products',
  startDate: '2025-01-01',
  endDate: '2025-01-31',
});
noResults.forEach(s => console.log(`"${s.search}" — ${s.count} times, 0 results`));

// Click-through rate and conversion rate
const { clickRate, conversionRate } = await client.getClickThroughRate({
  index: 'products',
});
console.log(`CTR: ${(clickRate * 100).toFixed(1)}%, CVR: ${(conversionRate * 100).toFixed(1)}%`);

Step 5: Database-to-Algolia Sync Pipeline

// Real-time index updates from your database change events
// Works with Prisma, Drizzle, Mongoose change streams, PostgreSQL LISTEN/NOTIFY

import { getClient } from './algolia/client';

// Prisma middleware example
prisma.$use(async (params, next) => {
  const result = await next(params);
  const client = getClient();

  if (params.model === 'Product') {
    switch (params.action) {
      case 'create':
      case 'update':
        await client.saveObject({
          indexName: 'products',
          body: {
            objectID: result.id,
            name: result.name,
            price: result.price,
            category: result.category,
          },
        });
        break;
      case 'delete':
        await client.deleteObject({
          indexName: 'products',
          objectID: params.args.where.id,
        });
        break;
    }
  }

  return result;
});

Error Handling

IssueCauseSolution
queryID is nullclickAnalytics: true not setAdd to search params
Events not appearing in dashboardWrong userToken formatUse stable, non-empty string identifiers
Analytics shows 0 CTREvents not correlatedEnsure queryID matches between search and click
Sync pipeline losing eventsNo retry on failureAdd dead-letter queue for failed updates

Resources

Next Steps

For performance optimization, see algolia-performance-tuning.

What ships with it

Read from the repository

Just SKILL.md. No reference files, no scripts.

Keep looking

Skills are one crate of 326,144. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.