Beacon 2.0 Technical Migration Guide
Your one stop shop on the key technical changes between Beacon 1.0 and Beacon 2.0 🚀
New to Athos Tracking? If you aren't currently using our legacy tracking, you can skip this migration guide and head straight to our Beacon 2.0 Documentation for a fresh implementation.
🏁 Getting Started: Beacon Migration
The Evolution: Batching to Referencing
Beacon 2.0 moves away from the "heavy lifting" of the legacy 1.0 environment. Previously, your implementation had to send massive batches of redundant product metadata (prices, images, names) for every interaction.
With Beacon 2.0, we’ve introduced a Reference-Based model. By utilizing a responseId from our API, our backend now handles the metadata mapping for you.
- Smaller Payloads: No more looping through product arrays.
- Better Performance: Lower browser overhead and faster execution.
- Cleaner Code: A simplified, intent-based event structure.
📖 Table of Contents
- Mapping Table - High-level architectural shifts.
- Developer Sandbox Mode - new testing parameters that wont impact reports
- Event Flow- new event structure and updated endpoints
- Render Events - Replacing
profile.render. - Impression Events - Viewport tracking best practices.
- Clickthrough Events - Tracking shopper intent.
🛠️ Breaking Changes and Mapping
Use this table to map your current 1.0 logic to the 2.0 structure.
| Feature / Endpoint | Status in 1.0 | Action in 2.0 | Notes |
|---|---|---|---|
| Base URL | /beacon | /beacon/v2/{siteId}/ | Each endpoint begins with /{siteId}/- Each store's siteId can be found in the SMC |
| Batching | Required | Removed | Batching is no longer required for 2.0. outside of Personalization impression events |
| Payload Envelope | Mixed | context + data | Strict requirements for both objects. |
| Payload Type | application/json | text/plain OR application/json | Every endpoint now accepts text/plain Post data. |
🏖️Developer Sandbox Mode
Beacon 2.0 has introduced a new developer-centric functionality, not available in 1.0, to streamline the API integration process. You can now test your event data pipelines without impacting your production analytics. API customers can now pass a dev field in the event payload's context object to facilitate seamless testing during development.
💻Code Example:
{
"context": {
...
"dev": "true",
...
}
- Purpose: Events sent with this flag are validated by the API to ensure your integration is working, but the data is not surfaced in your production reports.
- Implementation Strategy: We strongly recommend implementing a global flag or environment variable in your codebase to handle enabling/disabling the dev flag. This allows you to toggle developer mode on or off across your entire site with a single update.
- Important Go-Live Step: This flag must be removed or set to false for your production launch. If the dev flag is enabled in your code after go-live, your performance reports will remain empty.
Troubleshooting - Note that 400 errors are an exception; these will still be captured and surfaced in the Beacon Data Quality Report regardless of the flag status. This ensures our internal teams can assist you in resolving implementation hurdles during the build phase.
🏗️ Resource-Specific Migration
🔄 Personalization: 1.0 vs 2.0 - The Logic Shift
In Beacon 2.0, the way we track recommendation events has been completely overhauled to reduce payload size and integration complexity.
🌊Event Flow
Typical event sequence for recommendations in Beacon 2.0:
- Render - When recommendations are requested from the API and rendered on the page. Uses the
/beacon/v2/{siteId}/recommendations/renderendpoint and replaces theprofile.renderandprofile.product.rendertypes from Beacon 1.0 - Impression - When recommended items enter the viewport. Uses the
/beacon/v2/{siteId}/recommendations/impressionendpoint and replaces theprofile.impressionandprofile.product.impressiontypes from Beacon 1.0 - Clickthrough- When a shopper clicks on a rendered Athos personalized recommended result, and is taken to the product detail page (PDP). Uses the
/beacon/v2/{siteId}/recommendations/clickthroughendpoint and replaces theprofile.clickandprofile.product.clicktypes from Beacon 1.0 - Add to Cart - This event is new with Beacon 2.0. Covers when the Shopper adds a Athos personalized recommendation result to the cart via a Quick Add to Cart button in the rendered product card. If frontend Quick Add to Cart is not implemented, omit usage of this endpoint. Uses the
/beacon/v2/{siteId}/recommendations/addtocartendpoint. View more about this new endpoint under our personalized recommendation tracking guide.
Beacon 2.0 Parameter: When using Beacon 2.0 tracking, you must include
beacon=truein your Recommendation API requests. This enables automatic tracking event generation by the API and ensures proper integration with the Beacon tracking system.
💰Event Payloads
Render Events
- In Beacon 1.0, you had to send a batch array containing a "Profile Render" event PLUS an individual "Product Render" event for every single product returned by the API.
- In Beacon 2.0, you send one event. By passing the responseId (returned by the Recommendations API), our backend automatically maps the products that were shown. No more looping through product arrays.
💻 Code Example
Beacon 1.0 (Old Batch Method) You had to build a complex array where the context was repeated for every single item.
[
{
"category" : "searchspring.recommendations.user-interactions",
"context" : {
"pageLoadId" : "e560933a-b0fe-408d-8df5-807270e79fb8",
"userId" : "e2cfa1b3-96bc-4857-b9ad-22f07af52403",
"sessionId" : "5b5baff8-0f18-4b56-8f4b-9a6ce13435a2",
"website" : {
"trackingCode" : "YOUR_SITE_ID"
}
},
"event": {
"context" : {
"type" : "product-recommendation",
"tag" : "home-recs",
"placement" : "home-page"
},
"profile" : {
"tag" : "home-recs",
"placement" : "home-page",
"seed" : [""]
}
},
"id" : "f77ce2b0-814f-44af-9caa-89fd75400991",
"type" : "profile.render"
},
{
"category" : "searchspring.recommendations.user-interactions",
"context" : {
"pageLoadId" : "e560933a-b0fe-408d-8df5-807270e79fb8",
"userId" : "e2cfa1b3-96bc-4857-b9ad-22f07af52403",
"sessionId" : "5b5baff8-0f18-4b56-8f4b-9a6ce13435a2",
"website" : {
"trackingCode" : "YOUR_SITE_ID"
}
},
"event": {
"context" : {
"type" : "product-recommendation",
"tag" : "home-recs",
"placement" : "home-page"
},
"product" : {
"id" : "123456789",
"mappings" : {
"core" : {
"imageUrl" : "https://example.com/images/123456789/image",
"msrp" : 24.99,
"name" : "Short Sleeve Shirt",
"price" : 14.99,
"sku" : "S_SLV_SHRT_XS",
"thumbnailImageUrl" : "https://example.com/images/123456789/thumbnailImage",
"uid" : "123456789",
"url" : "https://example.com/products/123456789"
}
}
}
},
"id" : "a97d55c5-77d2-4b0f-939d-5d4b0de15f63",
"pid" : "f77ce2b0-814f-44af-9caa-89fd75400991",
"type" : "profile.product.render"
},
{
"category" : "searchspring.recommendations.user-interactions",
"context" : {
"pageLoadId" : "e560933a-b0fe-408d-8df5-807270e79fb8",
"userId" : "e2cfa1b3-96bc-4857-b9ad-22f07af52403",
"sessionId" : "5b5baff8-0f18-4b56-8f4b-9a6ce13435a2",
"website" : {
"trackingCode" : "YOUR_SITE_ID"
}
},
"event": {
"context" : {
"type" : "product-recommendation",
"tag" : "home-recs",
"placement" : "home-page"
},
"product" : {
"id" : "987654321",
"mappings" : {
"core" : {
"imageUrl" : "https://example.com/images/987654321/image",
"msrp" : 29.99,
"name" : "Long Sleeve shirt",
"price" : 19.99,
"sku" : "LNG_SLV_SHRT_XS",
"thumbnailImageUrl" : "https://example.com/images/987654321/thumbnailImage",
"uid" : "987654321",
"url" : "https://example.com/products/987654321"
}
}
}
},
"id" : "20902d3f-3aa0-436e-8920-af4f1fcd7ee1 ",
"pid" : "f77ce2b0-814f-44af-9caa-89fd75400991",
"type" : "profile.product.render"
},
{
"category" : "searchspring.recommendations.user-interactions",
"context" : {
"pageLoadId" : "e560933a-b0fe-408d-8df5-807270e79fb8",
"userId" : "e2cfa1b3-96bc-4857-b9ad-22f07af52403",
"sessionId" : "5b5baff8-0f18-4b56-8f4b-9a6ce13435a2",
"website" : {
"trackingCode" : "YOUR_SITE_ID"
}
},
"event": {
"context" : {
"type" : "product-recommendation",
"tag" : "home-recs",
"placement" : "home-page"
},
"product" : {
"id" : "543216789",
"mappings" : {
"core" : {
"imageUrl" : "https://example.com/images/543216789/image",
"msrp" : 19.99,
"name" : "Tank Top",
"price" : 13.99,
"sku" : "TNK_TOP_XS",
"thumbnailImageUrl" : "https://example.com/images/543216789/thumbnailImage",
"uid" : "543216789",
"url" : "https://example.com/products/543216789"
}
}
}
},
"id" : "20902d3f-3aa0-436e-8920-af4f1fcd7ee1 ",
"pid" : "f77ce2b0-814f-44af-9caa-89fd75400991",
"type" : "profile.product.render"
}
]Beacon 2.0 (New Reference Method)
The new endpoint /recommendations/render replaces profile.render and profile.product.render while handling everything via the responseId provided in the initial API response.
{
"context": {
"userId": "e2cfa1b3-96bc-4857-b9ad-22f07af52403",
"sessionId": "5b5baff8-0f18-4b56-8f4b-9a6ce13435a2",
"pageLoadId": "e560933a-b0fe-408d-8df5-807270e79fb8",
"pageUrl": "https://example.com/",
"timestamp": "2026-01-26T15:04:05Z",
"userAgent": "Mozilla/5.0...",
"initiator": "searchspring/snap/preact/0.49.1"
},
"data": {
"tag": "home-recs",
"responseId": "f77ce2b0-814f-44af-9caa-89fd75400991",
}
}Implementation Tip: When calling the Personalized Recommendations API, ensure you capture the
responseIdfrom the JSON response header or body to use in your Beacon 2.0 calls.
Required Body Parameters: Render
| Beacon 1.0 (Required) | Type | Beacon 2.0 (Required) | Type | Notes |
|---|---|---|---|---|
| type | string | (Removed) | N/A | Handled by the endpoint URL |
| category | string | (Removed) | N/A | Handled by the endpoint URL |
| id / pid | string | data.responseId | string | Connects the event to the API response |
| event | object | data | object | Top-level wrapper for event data |
| data.tag | string | The recommendation profile tag | ||
| context | object | Top-level wrapper for contextual data about the event | ||
| context.userId | string | Found in athos-user-id cookie | ||
| context.sessionId | string | Found in athos-session-id cookie. Should expire after store visit. | ||
| context.pageLoadId | string | Unique identifier that represents a unique page load. | ||
| context.pageUrl | string | The current page URL | ||
| context.timestamp | string | RFC3339 formatted timestamp | ||
| context.initiator | string | Application identifier that initiated the event |
Practice Sending Beacon Render Events with 2.0
Get started with Beacon Render events by using our Native fetch example below!
/** Beacon 2.0 Render Event*/
/** Link this to your recommendation carousel mount/render logic.*/
/**Pass your responseId from the recommendation API request, and tag data as parameters*/
/**Adjust hard coded values to be dynamic as needed*/
const sendBeaconRenderEvent = async (responseId, tag) => {
const url = 'https://analytics.athoscommerce.net/beacon/v2/{siteId}/recommendations/render';
const payload = {
context: {
userId: "c1dbf50e-d9fd-427e-899e-ea2ce9e95620", // Found in athos-user-id cookie
sessionId: "b2bc321a-a1fb-411d-911b-fa2ce9e95611", // Found in athos-session-id cookie
pageLoadId: window.ssPageLoadId || "generate-unique-uuid-per-page",
pageUrl: window.location.href,
timestamp: new Date().toISOString(),
initiator: "custom-site-integration"
},
data: {
tag: tag,
responseId: responseId
}
};
try {
const response = await fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json'
},
body: JSON.stringify(payload),
keepalive: true
});
if (response.ok) {
console.log('Beacon sent successfully');
}
} catch (error) {
console.error('Beacon Error: ', error);
}
};
Impression Events
In Beacon 1.0, tracking impressions was a heavy manual task. You had to send a batch array containing a "Profile Impression" event PLUS an individual "Product Impression" event for every single product that entered the viewport. Each of those objects required repeating the full context and product metadata (name, price, image URL).
In Beacon 2.0, we use a Lightweight Reference method. Instead of re-sending product metadata, you simply send an array of the uid and parentId for the products currently in view. Our backend uses the responseId to map the rest of the details automatically.
💻 Code Example
Beacon 1.0 (Old Batch Method) Developers had to loop through visible items and construct an array of objects, each containing the full product mapping and redundant context.
[
{
"category" : "searchspring.recommendations.user-interactions",
"context" : {
"pageLoadId" : "e560933a-b0fe-408d-8df5-807270e79fb8",
"userId" : "e2cfa1b3-96bc-4857-b9ad-22f07af52403",
"sessionId" : "5b5baff8-0f18-4b56-8f4b-9a6ce13435a2",
"website" : {
"trackingCode" : "YOUR_SITE_ID"
}
},
"event": {
"context" : {
"type" : "product-recommendation",
"tag" : "home-recs",
"placement" : "home-page"
},
"profile" : {
"tag" : "home-recs",
"placement" : "home-page",
"seed" : [""]
}
},
"id" : "f77ce2b0-814f-44af-9caa-89fd75400991",
"type" : "profile.impression"
},
{
"category" : "searchspring.recommendations.user-interactions",
"context" : {
"pageLoadId" : "e560933a-b0fe-408d-8df5-807270e79fb8",
"userId" : "e2cfa1b3-96bc-4857-b9ad-22f07af52403",
"sessionId" : "5b5baff8-0f18-4b56-8f4b-9a6ce13435a2",
"website" : {
"trackingCode" : "YOUR_SITE_ID"
}
},
"event": {
"context" : {
"type" : "product-recommendation",
"tag" : "home-recs",
"placement" : "home-page"
},
"product" : {
"id" : "123456789",
"mappings" : {
"core" : {
"imageUrl" : "https://example.com/images/123456789/image",
"msrp" : 24.99,
"name" : "Short Sleeve Shirt",
"price" : 14.99,
"sku" : "S_SLV_SHRT_XS",
"thumbnailImageUrl" : "https://example.com/images/123456789/thumbnailImage",
"uid" : "123456789",
"url" : "https://example.com/products/123456789"
}
}
}
},
"id" : "a97d55c5-77d2-4b0f-939d-5d4b0de15f63",
"pid" : "f77ce2b0-814f-44af-9caa-89fd75400991",
"type" : "profile.product.impression"
},
{
"category" : "searchspring.recommendations.user-interactions",
"context" : {
"pageLoadId" : "e560933a-b0fe-408d-8df5-807270e79fb8",
"userId" : "e2cfa1b3-96bc-4857-b9ad-22f07af52403",
"sessionId" : "5b5baff8-0f18-4b56-8f4b-9a6ce13435a2",
"website" : {
"trackingCode" : "YOUR_SITE_ID"
}
},
"event": {
"context" : {
"type" : "product-recommendation",
"tag" : "home-recs",
"placement" : "home-page"
},
"product" : {
"id" : "987654321",
"mappings" : {
"core" : {
"imageUrl" : "https://example.com/images/987654321/image",
"msrp" : 29.99,
"name" : "Long Sleeve shirt",
"price" : 19.99,
"sku" : "LNG_SLV_SHRT_XS",
"thumbnailImageUrl" : "https://example.com/images/987654321/thumbnailImage",
"uid" : "987654321",
"url" : "https://example.com/products/987654321"
}
}
}
},
"id" : "20902d3f-3aa0-436e-8920-af4f1fcd7ee1 ",
"pid" : "f77ce2b0-814f-44af-9caa-89fd75400991",
"type" : "profile.product.impression"
}
]Beacon 2.0 (New Reference Method) The new endpoint /recommendations/impression allows you to send one clean object. You only need to pass the IDs of the products the shopper actually saw. The new endpoint /beacon/v2/{siteId}/recommendations/impression replaces the old profile.impression and profile.product.impression types.
{
"context": {
"IP": "7309:1fdb:e0d5:7632:7f2a:c269:7519:991b",
"userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36",
"timestamp": "2024-06-11T17:47:04.075876Z",
"pageUrl": "https://bocachica.searchspring.com/collections/mens/products/adventure-shorts-pitch-black",
"userId": "41f87850-65f5-4546-851c-f166109e57b9",
"sessionId": "1c311c14-c33b-4222-952a-f17db729ea31",
"pageLoadId": "080d179f-0034-4278-8d3c-dfba71c9b897",
"shopperId": "user123456",
"initiator": "searchspring/snap/preact/0.49.1",
"attribution": [
{
"type": "email",
"id": "1234567890"
}
],
"currency": {
"code": "USD"
}
},
"data": {
"responseId": "42c2dc64-d203-4d74-8122-515f26afb253",
"tag": "similar",
"results": [
{
"type": "product",
"parentId": "8128331911111",
"uid": "8128331907370"
},
{
"type": "product",
"parentId": "8128331922222",
"uid": "8128021070122"
},
{
"type": "product",
"parentId": "8128331933333",
"uid": "8127879741738"
},
{
"type": "product",
"parentId": "8128331944444",
"uid": "8128173736234"
},
{
"type": "product",
"parentId": "8128331955555",
"uid": "8128273711402"
},
{
"type": "product",
"parentId": "8128331966666",
"uid": "8128028737834"
}
],
"banners": []
}
}Implementation Tip: Only send products that are currently visible in the shopper's viewport. If a shopper scrolls further and sees more products, trigger a new impression event for only the newly visible items. We suggest a
70%threshold for product card visibility to trigger an impression event. To accurately track these impressions, we recommend using the Intersection Observer API. This API allows you to trigger events only when a product enters the visible area of the carousel.
Required Body Parameters: Impressions
| Beacon 1.0 (Required) | Type | Beacon 2.0 (Required) | Type | Note |
|---|---|---|---|---|
| type | string | (Removed) | N/A | Handled by endpoint URL path |
| category | string | (Removed) | N/A | Handled by endpoint URL path |
| event | object | data | object | Top-level wrapper for event data |
id / pid | string | data.responseId | string | Connects event to the API response |
| context | object | Top-level wrapper for contextual data about the event | ||
| data.tag | string | The recommendation profile tag | ||
| data.banners | array | Use [] if no banners returned | ||
| context.userId | string | Unique identifier for the customer | ||
| context.sessionId | string | Unique identifier for current session | ||
| context.pageLoadId | string | Unique ID for the specific page load | ||
| context.pageUrl | string | Current window.location.href | ||
| context.timestamp | string | RFC3339 formatted timestamp | ||
| context.initiator | string | App identifier that initiated event |
Inside the data.results Array (2.0):
Each product object in the array must contain:
type: (string) Typically "product"uid: (string) The unique product IDparentId: (string) The parent product ID (use same asuidif no parent exists)
Practice Sending Beacon Impression Events with 2.0
Get started with beacon impression events by using our native fetch example below!
/**
* Beacon 2.0 Impression Event
* Trigger this as products scroll into view.
* * @param {string} responseId - The unique ID from the Athos API response
* @param {string} tag - The profile tag (e.g., "home-recs")
* @param {Array} visibleProducts - Array of objects: { type, parentId, uid }
*/
const sendBeaconImpressionEvent = async (responseId, tag, visibleProducts) => {
// Replace {siteId} with your 6-character Athos Site ID
const url = 'https://analytics.athoscommerce.net/beacon/v2/{siteId}/recommendations/impression';
const payload = {
context: {
userId: "c1dbf50e-d9fd-427e-899e-ea2ce9e95620", // Typically from athos-user-id cookie
sessionId: "b2bc321a-a1fb-411d-911b-fa2ce9e95611", // Typically from athos-session-id cookie
pageLoadId: window.ssPageLoadId || "generate-unique-uuid",
pageUrl: window.location.href,
timestamp: new Date().toISOString(), // RFC3339/ISO 8601
initiator: "custom-site-integration",
userAgent: navigator.userAgent,
// shopperId: "[email protected]" // Include if the user is logged in
},
data: {
responseId: responseId, // The ID from the Recommendations API response
tag: tag, // e.g., "home-recs"
results: visibleProducts, // Array of { type: "product", parentId: "123", uid: "123" }
banners: [] // Must be an array, even if empty
}
};
try {
const response = await fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
// OR 'text/plain' to avoid CORS preflight (OPTIONS) requests
},
body: JSON.stringify(payload),
keepalive: true
});
if (response.ok) {
console.log('Impression Beacon sent successfully');
} else {
const errorData = await response.json();
console.error('Beacon 2.0 Error:', errorData);
}
} catch (error) {
console.error('Network Error:', error);
}
};
// --- Example Usage with Intersection Observer ---//
/** Trigger new impression events as products scroll into view.*/
const observer = new IntersectionObserver((entries) => {
//The isIntersecting property is a boolean provided by the browser you can use in this case. It tells us when a specific element has actually entered the shopper's view.
const visible = entries
.filter(entry => entry.isIntersecting)
.map(entry => ({
type: "product",
parentId: entry.target.dataset.parentId,
uid: entry.target.dataset.uid
}));
if (visible.length > 0) {
// Send the beacon for only the visible products
sendBeaconImpressionEvent("f77ce2b0-814f-44af-9caa-89fd75400991", "home-recs", visible);
// Unobserve after tracking if you only want to count the first view
entries.forEach(entry => observer.unobserve(entry.target));
}
}, { threshold: 0.7 }); // We suggest triggering when 70% of the product card is visible
// Attach observer to your product cards, update selector as needed
document.querySelectorAll('.athos-recs-product').forEach(el => observer.observe(el));Clickthrough Events
In Beacon 1.0, tracking a click was a heavy, multi-step batch process. You had to send a profile.click event to register the interaction with the carousel, followed by a profile.product.click event containing the full metadata (name, price, SKU, etc.) of the specific product clicked.
In Beacon 2.0, we use a Lightweight Reference method. This consolidates the interaction into a single, streamlined request to the /clickthrough endpoint. By simply passing the responseId and the specific product uid, our backend automatically attributes the click to the correct recommendation profile and product details without needing redundant metadata.
💻 Code Example
Beacon 1.0 (Old Batch Method) Developers had to send an array containing both the profile interaction and the full product mapping and redundant context.
[
{
"category" : "searchspring.recommendations.user-interactions",
"context" : {
"pageLoadId" : "e560933a-b0fe-408d-8df5-807270e79fb8",
"userId" : "e2cfa1b3-96bc-4857-b9ad-22f07af52403",
"sessionId" : "5b5baff8-0f18-4b56-8f4b-9a6ce13435a2",
"website" : {
"trackingCode" : "YOUR_SITE_ID"
}
},
"event": {
"context" : {
"type" : "product-recommendation",
"tag" : "home-recs",
"placement" : "home-page"
},
"profile" : {
"tag" : "home-recs",
"placement" : "home-page",
"seed" : [""]
}
},
"id" : "f77ce2b0-814f-44af-9caa-89fd75400991",
"type" : "profile.click"
},
{
"category" : "searchspring.recommendations.user-interactions",
"context" : {
"pageLoadId" : "e560933a-b0fe-408d-8df5-807270e79fb8",
"userId" : "e2cfa1b3-96bc-4857-b9ad-22f07af52403",
"sessionId" : "5b5baff8-0f18-4b56-8f4b-9a6ce13435a2",
"website" : {
"trackingCode" : "YOUR_SITE_ID"
}
},
"event": {
"context" : {
"type" : "product-recommendation",
"tag" : "home-recs",
"placement" : "home-page"
},
"product" : {
"id" : "543216789",
"mappings" : {
"core" : {
"imageUrl" : "https://example.com/images/543216789/image",
"msrp" : 19.99,
"name" : "Tank Top",
"price" : 13.99,
"sku" : "TNK_TOP_XS",
"thumbnailImageUrl" : "https://example.com/images/543216789/thumbnailImage",
"uid" : "543216789",
"url" : "https://example.com/products/543216789"
}
}
}
},
"id" : "20902d3f-3aa0-436e-8920-af4f1fcd7ee1 ",
"pid" : "f77ce2b0-814f-44af-9caa-89fd75400991",
"type" : "profile.product.click"
}
]Beacon 2.0 (New Reference Method) The new endpoint /recommendations/clickthrough replaces the old profile.click and profile.product.click types with one clean object.
{
"context": {
"IP": "89.76.6.25",
"userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36",
"timestamp": "2006-01-02T15:04:05Z",
"pageUrl": "https://bocachica.searchspring.com/collections/shop?q=shirt&view=products",
"userId": "41f87850-65f5-4546-851c-f166109e57b9",
"sessionId": "1c311c14-c33b-4222-952a-f17db729ea31",
"pageLoadId": "080d179f-0034-4278-8d3c-dfba71c9b897",
"shopperId": "user123456",
"initiator": "searchspring/snap/preact/0.49.1",
"currency": {
"code": "USD"
}
},
"data": {
"responseId": "a907d0ad-720a-4666-b046-00c0c28fb78d",
"tag": "similar",
"results": [
{
"type": "product",
"parentId": "8128331911111",
"uid": "8128331907370"
}
]
}
}Required Body Parameters: Clickthrough
| Beacon 1.0 (Required) | Type | Beacon 2.0 (Required) | Type | Note |
|---|---|---|---|---|
| type | string | (Removed) | N/A | Handled by endpoint URL path (/clickthrough) |
| category | string | (Removed) | N/A | Handled by endpoint URL path |
| event | object | data | object | Top-level wrapper for event-specific data |
| id / pid | string | data.responseId | string | Connects the click to the original API response |
| data.tag | string | The recommendation profile tag (e.g., "home-recs") | ||
| data.results | array | Array containing the clicked item { type, uid } | ||
| context | object | Top-level wrapper for contextual shopper data | ||
| context.userId | string | Unique identifier for the customer | ||
| context.sessionId | string | Unique identifier for current session | ||
| context.pageLoadId | string | Unique ID for the specific page load | ||
| context.pageUrl | string | Current window.location.href | ||
| context.timestamp | string | RFC3339 formatted timestamp | ||
| context.initiator | string | App identifier that initiated event |
Inside the data.results Array (2.0):
Each product object in the array must contain:
type: (string) Typically "product"uid: (string) The unique product IDparentId: (string) The parent product ID (use same asuidif no parent exists)
Practice Sending Beacon Clickthrough events with 2.0
Practice sending beacon clickthrough events with our native fetch example below
/**
* Tracks a recommendation clickthrough using Beacon 2.0
* @param {string} responseId - From the original recommendations API response
* @param {string} productUid - The UID of the product being clicked
* @param {string} profileTag - The tag of the recommendation profile (e.g., 'similar')
*/
async function trackRecommendationClick(responseId, productUid, profileTag) {
const url = 'https://analytics.athoscommerce.net/beacon/v2/{siteId}/recommendations/clickthrough';
const payload = {
context: {
userId: "41f87850-65f5-4546-851c-f166109e57b9", // Typically from a cookie
sessionId: "1c311c14-c33b-4222-952a-f17db729ea31",
pageLoadId: "080d179f-0034-4278-8d3c-dfba71c9b897",
pageUrl: window.location.href,
timestamp: new Date().toISOString(), // RFC3339 format
userAgent: navigator.userAgent,
initiator: "your-app-name/1.0.0"
},
data: {
responseId: responseId,
tag: profileTag,
results: [
{
type: "product",
uid: productUid,
parentId: productUid // Use UID if no parent exists
}
]
}
};
try {
const response = await fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(payload)
});
if (!response.ok) {
throw new Error(`Beacon error: ${response.statusText}`);
}
console.log('Clickthrough tracked successfully');
} catch (error) {
console.error('Failed to send beacon:', error);
}
}
// --- Example Usage ---
// This would be triggered by an onClick event on your carousel item
// trackRecommendationClick('a907d0ad-720a-4666-b046-00c0c28fb78d', '8128331907370', 'home-recs');Implementation Tip: When a user clicks a product link, the browser usually navigates away immediately, which might cancel your fetch request. To prevent this, you can use the keepalive: true flag in your fetch options or use navigator.sendBeacon() if you want to ensure the data reaches the server without delaying the page transition.
🚦Ready to Begin? No, Ready to Beacon.
This concludes the 1 to 1 mappings between Beacon 1.0 and Beacon 2.0. You’ve successfully mapped your legacy 1.0 logic to the 2.0 structure! Now that you have updated your existing beaconing, the next step is diving headfirst into our expanded beaconing options!
Updated about 1 month ago