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


🛠️ Breaking Changes and Mapping

Use this table to map your current 1.0 logic to the 2.0 structure.

Feature / EndpointStatus in 1.0Action in 2.0Notes
Base URL/beacon/beacon/v2/{siteId}/Each endpoint begins with /{siteId}/- Each store's siteId can be found in the SMC
BatchingRequiredRemovedBatching is no longer required for 2.0. outside of Personalization impression events
Payload EnvelopeMixedcontext + dataStrict requirements for both objects.
Payload Typeapplication/jsontext/plain OR application/jsonEvery 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:

  1. Render - When recommendations are requested from the API and rendered on the page. Uses the /beacon/v2/{siteId}/recommendations/render endpoint and replaces the profile.render and profile.product.render types from Beacon 1.0
  2. Impression - When recommended items enter the viewport. Uses the /beacon/v2/{siteId}/recommendations/impression endpoint and replaces the profile.impression and profile.product.impression types from Beacon 1.0
  3. 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/clickthrough endpoint and replaces the profile.click and profile.product.click types from Beacon 1.0
  4. 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/addtocart endpoint. 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=true in 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 responseId from the JSON response header or body to use in your Beacon 2.0 calls.

Required Body Parameters: Render

Beacon 1.0 (Required)TypeBeacon 2.0 (Required)TypeNotes
typestring(Removed)N/AHandled by the endpoint URL
categorystring(Removed)N/AHandled by the endpoint URL
id / pidstringdata.responseIdstringConnects the event to the API response
eventobjectdataobjectTop-level wrapper for event data
data.tagstringThe recommendation profile tag
contextobjectTop-level wrapper for contextual data about the event
context.userIdstringFound in athos-user-id cookie
context.sessionIdstringFound in athos-session-id cookie. Should expire after store visit.
context.pageLoadIdstringUnique identifier that represents a unique page load.
context.pageUrlstringThe current page URL
context.timestampstringRFC3339 formatted timestamp
context.initiatorstringApplication 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)TypeBeacon 2.0 (Required)TypeNote
typestring(Removed)N/AHandled by endpoint URL path
categorystring(Removed)N/AHandled by endpoint URL path
eventobjectdataobjectTop-level wrapper for event data
id / pidstringdata.responseIdstringConnects event to the API response
contextobjectTop-level wrapper for contextual data about the event
data.tagstringThe recommendation profile tag
data.bannersarrayUse [] if no banners returned
context.userIdstringUnique identifier for the customer
context.sessionIdstringUnique identifier for current session
context.pageLoadIdstringUnique ID for the specific page load
context.pageUrlstringCurrent window.location.href
context.timestampstringRFC3339 formatted timestamp
context.initiatorstringApp 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 ID
  • parentId: (string) The parent product ID (use same as uid if 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)TypeBeacon 2.0 (Required)TypeNote
typestring(Removed)N/AHandled by endpoint URL path (/clickthrough)
categorystring(Removed)N/AHandled by endpoint URL path
eventobjectdataobjectTop-level wrapper for event-specific data
id / pidstringdata.responseIdstringConnects the click to the original API response
data.tagstringThe recommendation profile tag (e.g., "home-recs")
data.resultsarrayArray containing the clicked item { type, uid }
contextobjectTop-level wrapper for contextual shopper data
context.userIdstringUnique identifier for the customer
context.sessionIdstringUnique identifier for current session
context.pageLoadIdstringUnique ID for the specific page load
context.pageUrlstringCurrent window.location.href
context.timestampstringRFC3339 formatted timestamp
context.initiatorstringApp 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 ID
  • parentId: (string) The parent product ID (use same as uid if 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!