Tracking Integration Guide
For continuous optimization of the search quality it is mandatory to track the search results and user interactions. QSC provides two types of tracking: automatic backend tracking and manual frontend tracking.
Overview
Automatic Backend Tracking
When you use the QSC search API, most search metrics are automatically tracked on the backend without any additional implementation:
- Timestamp
- Search Query
- Total hits for the query
- Pagination
- Number of displayed results of the current page
- Used filters with values
- Used sorting
- Displayed documents
- Internal search time
- IP address
- User agent
- Referrer
- Session id
- Request id
- User id
Frontend Analytics Tracking
User interactions that don't go through the search backend must be tracked manually using the analytics API:
| Event Type | Description | When to Use |
|---|---|---|
| clickDocument | User clicks on a search result | When user navigates to a document |
| addToCart | User adds item to cart from search results | E-commerce: Add to cart button clicked |
| clickFacet | User clicks on a facet/filter value | When user applies a filter |
| visit | User views a document/page | Track page views independent of search |
| like | User likes/favorites a document | User engagement tracking |
| order | User completes a purchase | E-commerce: Order confirmation |
| feedback | User provides feedback on results | User satisfaction tracking |
Quick Start Checklist
To integrate tracking in your application:
- Obtain your
tenantandcodevalues from your QSC administrator - Implement identifier tracking (requestId, sessionId, userId)
- Ensure requestId is passed from search responses to subsequent requests
- Integrate analytics events for user actions (clicks, add to cart, etc.)
- Test your implementation using the examples provided below
Understanding Identifiers
To correlate tracking data across search requests and user interactions, QSC uses three types of identifiers. These identifiers must be consistently passed in both search requests and analytics events.
| Identifier | Scope | Description | Examples |
|---|---|---|---|
| requestId | Request | Identifies a single search session with all related actions (pagination, filtering, sorting) | Generated per search query |
| sessionId | Session | Identifies a user session (typically 30 minutes) | Session cookie, UUID |
| userId | User | Identifies a user permanently across sessions | Hashed email, customer ID, UUID |
Important: All three identifiers should be included in both search requests and analytics events to enable proper correlation of tracking data.
Client-Side Caching Consideration
Many frameworks (e.g., GraphQL with Apollo Client) cache search requests in the frontend. When caching is enabled, subsequent requests may not reach the backend, preventing server-side tracking. In these cases, it is essential to implement client-side tracking using the analytics API to capture all user interactions.
RequestId
The requestId groups all actions related to a single search query. When a user submits a new search, a new requestId is generated. All subsequent interactions with that search result (pagination, sorting, filtering, clicking documents) must use the same requestId.
Lifecycle:
- User submits new search query → New requestId is generated
- User paginates, sorts, or filters → Same requestId is reused
- User submits different search query → New requestId is generated
Implementation: If your client does not generate a requestId, the backend will automatically create one and return it in the response. You must then use this requestId for all subsequent requests related to that search.
Example - Initial Search Request:
https://qsc-dev.quasiris.de/api/v1/search/demo/trendware?q=schuhe
{
"statusCode": 200,
"requestId" : "69e0320e-e2aa-4f1e-94f3-5a440c9f55db",
"result": {},
"time": 31,
"currentTime": "2021-05-26T06:00:12+0000",
"request": {}
}
The requestId 69e0320e-e2aa-4f1e-94f3-5a440c9f55db is automatically generated by the backend.
If the user is paginating, sorting, filtering the search result, the initial generated requestId must be sent for each request to the backend.
Example with Paging
{
"statusCode": 200,
"requestId" : "69e0320e-e2aa-4f1e-94f3-5a440c9f55db",
"result": {},
"time": 31,
"currentTime": "2021-05-26T06:00:12+0000",
"request": {}
}
Session Id
The sessionId identifies a user's session, which typically encompasses multiple search requests and interactions. A new session is started after 30 minutes of inactivity.
Implementation Options:
- Website Session Cookie: Use your existing website session cookie value for consistency across your application
- Manual Generation: Generate a UUID/GUID and store it in sessionStorage or a cookie with appropriate expiration
Best Practice: A session should persist across multiple searches, page navigations, and interactions until the user leaves or the session expires.
User Id
The userId identifies a user permanently across multiple sessions and devices.
Implementation Options:
- Authenticated Users: Use customer ID, account number, or hashed email
- Anonymous Users: Generate a persistent identifier stored in localStorage or a long-lived cookie
Privacy Considerations:
- The search system does not require personally identifiable information (PII)
- It is recommended to use a hashed value (e.g., SHA-256 of email) rather than raw data
- The hash value must be consistent for the same user across sessions
- Ensure compliance with privacy regulations (GDPR, CCPA) in your implementation
Example: If a user's email is user@example.com, you could use sha256(user@example.com) as the userId.
Frontend Analytics Integration
While search queries are automatically tracked by the backend, user interactions like clicking search results, adding items to cart, or applying filters happen in the frontend and are not automatically captured. These actions must be tracked explicitly using the analytics API.
How It Works
When a user performs an action (clicks a result, adds to cart, etc.), your frontend application sends an HTTP POST request to the analytics endpoint with event details.
Analytics Endpoint URL Structure
The analytics endpoint follows this pattern:
https://qsc-dev.quasiris.de/api/v1/analytics/{tenant}/{code}
| parameter | description |
|---|---|
| tenant | Your tenant identifier (e.g., demo) |
| code | The search configuration code (e.g., trendware) |
For example: https://qsc-dev.quasiris.de/api/v1/analytics/demo/trendware
Example Request:
In the example below the user searched for "schuhe" on page 1 and clicked the first document with the id 4711.
curl -XPOST https://qsc-dev.quasiris.de/api/v1/analytics/demo/trendware -H "content-type: application/json" -d '
{
"type" : "clickDocument",
"requestId" : "04df50a2-4110-4a66-b1ff-a469bb94ad37",
"userId" : "579434e9-4c88-42b6-9f65-b79fc6f0d98d",
"sessionId" : "a9b2527f-69df-4b01-af54-3b51f0f892ee",
"q" : "schuhe",
"docId" : "4711",
"position" : 1,
"page" : 1
}'
Common Event Attributes
The following attributes are commonly used across different event types. Each specific event type may require or allow different combinations of these attributes.
| Attribute | Type | Required | Description |
|---|---|---|---|
| type | String | Yes | The event type: clickDocument, addToCart, clickFacet, visit, like, order |
| requestId | String | Conditional | Required for search-related events. The requestId from the search response. |
| userId | String | Yes | A unique identifier for the user (permanent across sessions) |
| sessionId | String | Yes | A unique identifier for the current session |
| q | String | Conditional | The search query. Required for search-related events. Optional for visit/like events. |
| docId | String | Conditional | Required for document-related events (clickDocument, addToCart, visit, like) |
| position | Integer | Optional | The position of the item on the page (1-indexed, not 0-indexed) |
| page | Integer | Optional | The page number where the item appeared |
| facetId | String | Conditional | Required for clickFacet events. The identifier of the facet. |
| facetValue | String | Conditional | Required for clickFacet events. The value that was selected. |
| id | String | Optional | Custom event ID. If not provided, a UUID is auto-generated. |
| timestamp | String | Optional | Event timestamp in ISO 8601 format (yyyy-MM-dd'T'HH:mm:ssZ). Defaults to current time. |
| orderId | String | Conditional | Required for order events. The order/transaction identifier. |
| ip | String | Optional | Client IP address for geo-analysis. |
| time | Long | Optional | Time metric in milliseconds (e.g., time spent on page). |
| locale | String | Optional | User locale/language code (e.g., en-US, de-DE). |
| filterName | String | Optional | The name of the filter applied. |
| additional | Object | Optional | Key-value map for custom data. Use this for extension fields. |
Response: The analytics endpoint returns an HTTP 200 status code on successful tracking. The response body is typically empty or contains a confirmation message.
Using the additional Field
The additional field is a flexible key-value map for custom tracking data that doesn't fit into the standard attributes. Data in this field is stored but not indexed for filtering or searching.
When to use:
- Custom business-specific metrics
- Deprecated fields (see migration guide below)
- Campaign or source attribution
- Extended product or user metadata
Structure:
- Accepts any valid JSON object
- Keys should be camelCase strings
- Values can be strings, numbers, booleans, arrays, or nested objects
Example with custom fields:
{
"type": "clickDocument",
"requestId": "04df50a2-4110-4a66-b1ff-a469bb94ad37",
"userId": "579434e9-4c88-42b6-9f65-b79fc6f0d98d",
"sessionId": "a9b2527f-69df-4b01-af54-3b51f0f892ee",
"docId": "4711",
"additional": {
"abTestVariant": "B",
"campaignId": "summer-sale-2024",
"deviceType": "mobile",
"customScore": 0.85,
"userSegments": ["premium", "returning"]
}
}
Note: Use top-level attributes for data you need to filter, aggregate, or search on. Use additional for supplementary data that you want to store for reference or export.
Deprecated Fields
The following fields are deprecated and should be moved to the additional block. They will continue to work at the top level for backwards compatibility, but new implementations should use the additional block instead.
| Deprecated Field | Type | Migration |
|---|---|---|
| answer | String | Use additional.answer |
| comment | String | Use additional.comment |
| commentOptions | List<String> | Use additional.commentOptions |
| rating | Integer | Use additional.rating |
| positionValue | Integer | Use additional.positionValue |
| selectedQuery | String | Use additional.selectedQuery |
| products | Object | Use additional.products |
Migration Example:
Instead of:
{
"type": "feedback",
"rating": 5,
"comment": "Great results!",
"commentOptions": ["relevant", "fast"]
}
Use:
{
"type": "feedback",
"additional": {
"rating": 5,
"comment": "Great results!",
"commentOptions": ["relevant", "fast"]
}
}
Best Practices
When to Generate New IDs
- requestId: Generate a new one each time a user submits a new search query
- sessionId: Generate once per session (expires after 30 minutes of inactivity)
- userId: Generate once per user and persist across sessions
Error Handling
- If an analytics request fails, consider queuing it for retry rather than blocking the user experience
- Log failed tracking requests for debugging but don't show errors to users
- Analytics tracking should never block or delay the user interface
Performance
- Send analytics events asynchronously (don't wait for response)
- Consider batching multiple events if your application generates many rapid interactions
- Use appropriate timeout values (1-2 seconds) for analytics requests
Privacy & Compliance
- Always hash or anonymize user identifiers when possible
- Respect user privacy preferences and opt-out settings
- Ensure compliance with GDPR, CCPA, and other relevant regulations
- Don't send sensitive personal information in tracking events
Use Cases & Examples
In this section we provide copy-paste ready examples for common tracking scenarios.
Note: Replace demo (tenant) and trendware (code) with your actual values.
Tracking clicks on documents
Use Case: Track when a user clicks on a search result to view the full document or product page.
In this example an analytics event is sent when the user clicks a document in a search result page.
Request:
curl -XPOST https://qsc-dev.quasiris.de/api/v1/analytics/demo/trendware -H "content-type: application/json" -d '
{
"type" : "clickDocument",
"requestId" : "04df50a2-4110-4a66-b1ff-a469bb94ad37",
"userId" : "579434e9-4c88-42b6-9f65-b79fc6f0d98d",
"sessionId" : "a9b2527f-69df-4b01-af54-3b51f0f892ee",
"q" : "schuhe",
"docId" : "4711",
"position" : 1,
"page" : 1
}'
| attributes | description |
|---|---|
| type | clickDocument - Click on a document |
| requestId | A unique id for the request. |
| userId | A unique id for the user. |
| sessionId | A unique id for the session. |
| q | The search query, which causes the result where document was clicked. |
| docId | A unique id for the document that was clicked. |
| position | The local position of the document of the current page that was clicked. The position starts at 1 not at 0. |
| page | The page of the document that was clicked. |
Tracking clicks on add to cart
Use Case: Track when a user adds a product to their shopping cart directly from the search results page.
In this example an analytics event is sent when the user clicks the add to cart button on the search result page.
Request:
curl -XPOST https://qsc-dev.quasiris.de/api/v1/analytics/demo/trendware -H "content-type: application/json" -d '
{
"type" : "addToCart",
"requestId" : "04df50a2-4110-4a66-b1ff-a469bb94ad37",
"userId" : "579434e9-4c88-42b6-9f65-b79fc6f0d98d",
"sessionId" : "a9b2527f-69df-4b01-af54-3b51f0f892ee",
"q" : "schuhe",
"docId" : "4711",
"position" : 1,
"page" : 1
}'
| attributes | description |
|---|---|
| type | addToCart - Click on addToCart |
| requestId | A unique id for the request. |
| userId | A unique id for the user. |
| sessionId | A unique id for the session. |
| q | The search query, which causes the result where document was clicked. |
| docId | A unique id for the document that was clicked. |
| position | The local position of the document of the current page that was clicked. The position starts at 1 not at 0. |
| page | The page of the document that was clicked. |
Tracking clicks on Facets
Use Case: Track when a user applies a filter (facet) to refine their search results.
In this example an analytics event is sent when the user clicks on a value of a facet on the search result page.
Request:
curl -XPOST https://qsc-dev.quasiris.de/api/v1/analytics/demo/trendware -H "content-type: application/json" -d '
{
"type" : "clickFacet",
"requestId" : "04df50a2-4110-4a66-b1ff-a469bb94ad37",
"userId" : "579434e9-4c88-42b6-9f65-b79fc6f0d98d",
"sessionId" : "a9b2527f-69df-4b01-af54-3b51f0f892ee",
"q" : "schuhe",
"facetId" : "color",
"facetValue" : "red",
"position" : 1,
"page" : 1
}'
| attributes | description |
|---|---|
| type | clickFacet - Click on a facet |
| requestId | A unique id for the request. |
| userId | A unique id for the user. |
| sessionId | A unique id for the session. |
| q | The search query, which causes the result where the facet was clicked. |
| facetId | A unique id for the facet that was clicked. In QSC this is provided in the search result. |
| facetValue | The value of the facet that was clicked. |
| position | The position of the facet that was clicked. |
| page | The page of the facet that was clicked. |
Tracking visits or likes on a document
Use Case: Track general page views or document engagement independent of search results.
In this example an analytics event is sent when a user views a document or page. This tracking is independent of search - the document does not need to have been shown in search results. This is useful for tracking general page views or document engagement across your entire site.
Request (Visit):
curl -XPOST https://qsc-dev.quasiris.de/api/v1/analytics/demo/trendware -H "content-type: application/json" -d '
{
"type" : "visit",
"userId" : "579434e9-4c88-42b6-9f65-b79fc6f0d98d",
"sessionId" : "a9b2527f-69df-4b01-af54-3b51f0f892ee",
"docId" : "my-page-id"
}'
| attributes | description |
|---|---|
| type | visit - visit of the page |
| userId | A unique id for the user. |
| sessionId | A unique id for the session. |
| docId | The id of the document. |
Tracking a Like:
To track a like event (user favorites or likes a document), use the same structure with type set to "like".
curl -XPOST https://qsc-dev.quasiris.de/api/v1/analytics/demo/trendware -H "content-type: application/json" -d '
{
"type" : "like",
"userId" : "579434e9-4c88-42b6-9f65-b79fc6f0d98d",
"sessionId" : "a9b2527f-69df-4b01-af54-3b51f0f892ee",
"docId" : "my-page-id"
}'
Tracking orders (E-commerce Conversion)
Use Case: Track when a user completes a purchase to measure search-to-conversion attribution.
In this example an analytics event is sent when the user completes an order after finding products through search.
Request:
curl -XPOST https://qsc-dev.quasiris.de/api/v1/analytics/demo/trendware -H "content-type: application/json" -d '
{
"type" : "order",
"requestId" : "04df50a2-4110-4a66-b1ff-a469bb94ad37",
"userId" : "579434e9-4c88-42b6-9f65-b79fc6f0d98d",
"sessionId" : "a9b2527f-69df-4b01-af54-3b51f0f892ee",
"orderId" : "ORD-2024-12345",
"additional" : {
"products" : [
{"docId": "4711", "quantity": 2, "price": 49.99},
{"docId": "4712", "quantity": 1, "price": 29.99}
]
}
}'
| attributes | description |
|---|---|
| type | order - A completed purchase |
| requestId | The requestId from the original search (for attribution) |
| userId | A unique id for the user. |
| sessionId | A unique id for the session. |
| orderId | A unique identifier for the order/transaction. |
| additional.products | Array of purchased products with docId, quantity, price. |
Tracking user feedback
Use Case: Track user satisfaction and feedback on search results.
In this example an analytics event is sent when a user submits feedback about search quality.
Request:
curl -XPOST https://qsc-dev.quasiris.de/api/v1/analytics/demo/trendware -H "content-type: application/json" -d '
{
"type" : "feedback",
"requestId" : "04df50a2-4110-4a66-b1ff-a469bb94ad37",
"userId" : "579434e9-4c88-42b6-9f65-b79fc6f0d98d",
"sessionId" : "a9b2527f-69df-4b01-af54-3b51f0f892ee",
"q" : "schuhe",
"additional" : {
"rating" : 4,
"comment" : "Good results but missing some brands",
"commentOptions" : ["relevant", "missing_items"]
}
}'
| attributes | description |
|---|---|
| type | feedback - User feedback on search results |
| requestId | The requestId from the search being rated. |
| userId | A unique id for the user. |
| sessionId | A unique id for the session. |
| q | The search query that was rated. |
| additional.rating | Numeric rating (e.g., 1-5 stars). |
| additional.comment | Free-text feedback from the user. |
| additional.commentOptions | Predefined feedback options selected by the user. |
Tracking suggest selections
Use Case: Track when a user selects a suggestion from the autocomplete/suggest dropdown.
Request:
curl -XPOST https://qsc-dev.quasiris.de/api/v1/analytics/demo/trendware -H "content-type: application/json" -d '
{
"type" : "clickDocument",
"userId" : "579434e9-4c88-42b6-9f65-b79fc6f0d98d",
"sessionId" : "a9b2527f-69df-4b01-af54-3b51f0f892ee",
"q" : "sch",
"position" : 3,
"additional" : {
"selectedQuery" : "schuhe damen"
}
}'
| attributes | description |
|---|---|
| type | clickDocument - Click on a suggest item |
| userId | A unique id for the user. |
| sessionId | A unique id for the session. |
| q | The partial query typed by the user. |
| position | The position of the suggestion in the dropdown (1-indexed). |
| additional.selectedQuery | The full suggestion text that was selected. |
Troubleshooting
Common Issues
Missing requestId:
- Ensure you're extracting the requestId from the search response and passing it to subsequent analytics events
- For non-search events (visit, like), requestId is optional
Events not appearing in analytics:
- Verify your tenant and code values are correct
- Check that the Content-Type header is set to
application/json - Ensure the request body is valid JSON
- Verify userId and sessionId are being consistently generated and passed
Inconsistent tracking data:
- Make sure you're using the same userId for the same user across all events
- Verify sessionId persists across page loads within the same session
- Check that requestId is reused for all actions related to the same search query
Testing Your Integration
- Use browser developer tools to inspect network requests to the analytics endpoint
- Verify request payload contains all required fields for each event type
- Check response codes - successful requests should return HTTP 200
- Monitor your QSC dashboard to confirm events are being received and processed
Next Steps
Once you've integrated tracking:
- Monitor analytics data in your QSC dashboard to verify events are being captured
- Set up alerts for tracking failures or anomalies
- Review user behavior patterns to optimize search relevance and user experience
- Iterate on your tracking implementation based on business needs and analytics insights
For additional support or questions about tracking integration, contact your QSC administrator or support team.