Skip to main content

Algolia Search Integration

Algolia replaces osTicket's built-in search with faceted, real-time full-text search. It powers the "My Queue" page and the global ticket search.


Overview

ComponentDetails
Client Libraryalgoliasearch (npm) + PHP API client
Index Namerhinotickets_index_dev
Key Filesinclude/custom/trait-algolia.php, include/custom/class.algolia.php
Frontendinstantsearch.js (Algolia UI widgets)
Maintenance Croncron-algolia.php

Architecture

Ticket Created/Updated
→ Algolia trait indexes ticket data
→ Ticket record pushed to Algolia index

Staff opens My Queue / Search
→ InstantSearch.js sends query to Algolia
→ Faceted results returned (department, status, priority, assignee)
→ Results displayed with hit highlighting

Index Configuration

Searchable Attributes

AttributeSource
subjectTicket subject line
ticket_numberDisplay number
user_nameClient name
user_emailClient email
organizationClient organization name
thread_contentCombined thread text (messages + responses)
ai_summaryAI-generated ticket summary

Facets (Filterable Attributes)

FacetPurpose
departmentFilter by department
statusFilter by ticket status
priorityFilter by priority level
assigned_toFilter by assigned staff
ai_urgencyFilter by AI urgency level
created_atDate-based filtering

Ranking

Custom ranking uses:

  • AI urgency percentage (descending)
  • Last updated timestamp (descending)
  • Priority level (descending)

PHP Integration

Trait: trait-algolia.php

Used by Suma\Ticket to index ticket data on create/update:

trait AlgoliaTrait
{
/**
* Push ticket data to Algolia index.
*
* @return void
*/
public function indexToAlgolia(): void
{
$record = [
'objectID' => $this->getId(),
'ticket_number' => $this->getNumber(),
'subject' => $this->getSubject(),
'status' => $this->getStatus()->getName(),
'department' => $this->getDeptName(),
'assigned_to' => $this->getAssignee(),
'ai_urgency' => $this->getAIUrgency(),
'created_at' => $this->getCreateDate(),
'updated_at' => $this->getLastUpdated(),
// ... additional fields
];

$index = $this->getAlgoliaIndex();
$index->saveObject($record);
}
}

Class: class.algolia.php

Manages the Algolia client connection and bulk operations:

// Initialize client
$client = Algolia\AlgoliaSearch\SearchClient::create(
ALGOLIA_APP_ID,
ALGOLIA_ADMIN_KEY
);
$index = $client->initIndex(ALGOLIA_INDEX);

Frontend Integration

My Queue Page (scp/my-queue.php)

Uses InstantSearch.js for real-time faceted search:

import { instantsearch, searchBox, hits, refinementList } from 'instantsearch.js';

const search = instantsearch({
indexName: 'rhinotickets_index_dev',
searchClient: algoliasearch(APP_ID, SEARCH_KEY),
});

search.addWidgets([
searchBox({ container: '#searchbox' }),
refinementList({ container: '#department-filter', attribute: 'department' }),
refinementList({ container: '#status-filter', attribute: 'status' }),
hits({ container: '#hits', templates: { item: hitTemplate } }),
]);

search.start();

Search Key (Frontend)

The frontend uses the Search-Only API Key (ALGOLIA_SEARCH_KEY) which has read-only access. The Admin Key is never exposed to the client.


Index Maintenance

Cron Job (cron-algolia.php)

Runs periodically to ensure index consistency:

  • Re-indexes tickets modified since last run
  • Removes deleted tickets from the index
  • Updates status/assignment changes that may have bypassed the trait

Manual Reindex

// Full reindex (use sparingly — resource intensive)
php cron-algolia.php --full

// Reindex a specific ticket
php cron-algolia.php --ticket=108749

Configuration

Settings in include/ost-config.php:

define('ALGOLIA_APP_ID', 'your_application_id');
define('ALGOLIA_ADMIN_KEY', 'your_admin_api_key');
define('ALGOLIA_SEARCH_KEY', 'your_search_only_key');
define('ALGOLIA_INDEX', 'rhinotickets_index_dev');

Troubleshooting

IssueSolution
Search returns no resultsRun php cron-algolia.php to rebuild index
Stale results (old status)Check that Algolia trait fires on status change
"Invalid API Key" errorVerify keys in ost-config.php match Algolia dashboard
Facets not filteringCheck attribute is configured as facet in Algolia dashboard
My Queue blankCheck browser console for JS errors; verify search key

Key Files

FilePurpose
include/custom/trait-algolia.phpAlgolia indexing trait for Suma\Ticket
include/custom/class.algolia.phpAlgolia client management and bulk operations
cron-algolia.phpIndex maintenance cron job
scp/my-queue.phpStaff My Queue page (InstantSearch frontend)
custom/src/js/algolia.jsFrontend InstantSearch module