Conversation
There was a problem hiding this comment.
Pull request overview
Adds support for including seed item IDs in recommendation tracking events so downstream analytics can associate a click/view event with the items that generated the recommendation set.
Changes:
- Extend recommendation click/view request bodies to include
seed_item_ids. - Add
seedItemIds(list) and convenienceseedItemId(single) overloads to recommendation tracking APIs. - Add tests validating that
seed_item_idsis serialized into recommendation click/view tracking requests.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 6 comments.
| File | Description |
|---|---|
| library/src/main/java/io/constructor/core/ConstructorIo.kt | Adds new parameters/overloads for recommendation click/view tracking and passes seed IDs into request bodies. |
| library/src/main/java/io/constructor/data/model/recommendations/RecommendationResultClickRequestBody.kt | Adds seed_item_ids field to click tracking request model. |
| library/src/main/java/io/constructor/data/model/recommendations/RecommendationResultViewRequestBody.kt | Adds seed_item_ids field to view tracking request model. |
| library/src/test/java/io/constructor/core/ConstructorIoTrackingTest.kt | Adds test coverage asserting seed_item_ids is included for single and multiple seeds. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| fun trackRecommendationResultsView(podId: String, numResultsViewed: Int, resultPage: Int? = null, resultCount: Int? = null, resultId: String? = null, sectionName: String? = null, url: String = "Not Available", analyticsTags: Map<String, String>? = null, seedItemIds: List<String>? = null) { | ||
| var completable = trackRecommendationResultsViewInternal(podId, null, numResultsViewed, resultPage, resultCount, resultId, sectionName, url, analyticsTags, seedItemIds) |
There was a problem hiding this comment.
trackRecommendationResultsView(podId, numResultsViewed, ...) gained a new trailing seedItemIds parameter, which changes the JVM method signature and will break binary compatibility for clients compiled against the prior version. To keep this non-breaking, reintroduce the previous signature as an overload delegating to the new one (with seedItemIds = null), and optionally deprecate it.
| /** | ||
| * Tracks recommendation result click events with a single seed item ID. | ||
| * | ||
| * @see trackRecommendationResultClick | ||
| */ | ||
| fun trackRecommendationResultClick(podId: String, strategyId: String, customerId: String, variationId: String? = null, sectionName: String? = null, resultId: String? = null, numResultsPerPage: Int? = null, resultPage: Int? = null, resultCount: Int? = null, resultPositionOnPage: Int? = null, analyticsTags: Map<String, String>? = null, seedItemId: String) { | ||
| trackRecommendationResultClick(podId, strategyId, customerId, variationId, sectionName, resultId, numResultsPerPage, resultPage, resultCount, resultPositionOnPage, analyticsTags, listOf(seedItemId)) |
There was a problem hiding this comment.
The new single-seed overload trackRecommendationResultClick(..., seedItemId: String) adds KDoc but omits an @param seedItemId tag (most public APIs in this file document parameters explicitly). Add the missing param documentation so generated docs clearly describe how this overload differs from the list-based one.
| /** | ||
| * Tracks recommendation result view events with a single seed item ID. | ||
| * | ||
| * @see trackRecommendationResultsView | ||
| */ | ||
| fun trackRecommendationResultsView(podId: String, itemIds: Array<String>, numResultsViewed: Int, resultPage: Int? = null, resultCount: Int? = null, resultId: String? = null, sectionName: String? = null, url: String = "Not Available", analyticsTags: Map<String, String>? = null, seedItemId: String) { | ||
| trackRecommendationResultsView(podId, itemIds, numResultsViewed, resultPage, resultCount, resultId, sectionName, url, analyticsTags, listOf(seedItemId)) | ||
| } |
There was a problem hiding this comment.
The new single-seed overload trackRecommendationResultsView(..., seedItemId: String) has KDoc but does not document the seedItemId parameter. Add an @param seedItemId entry (and any other notable behavior differences) to keep public API docs consistent and clear.
| /** | ||
| * Tracks recommendation result view events with a single seed item ID. | ||
| * | ||
| * @see trackRecommendationResultsView | ||
| */ | ||
| fun trackRecommendationResultsView(podId: String, numResultsViewed: Int, resultPage: Int? = null, resultCount: Int? = null, resultId: String? = null, sectionName: String? = null, url: String = "Not Available", analyticsTags: Map<String, String>? = null, seedItemId: String) { | ||
| trackRecommendationResultsView(podId, numResultsViewed, resultPage, resultCount, resultId, sectionName, url, analyticsTags, listOf(seedItemId)) | ||
| } |
There was a problem hiding this comment.
The added single-seed overload trackRecommendationResultsView(podId, numResultsViewed, ..., seedItemId: String) is public API but its KDoc omits an @param seedItemId tag. Add the param documentation for consistency with the rest of the tracking APIs and to improve generated docs.
| fun trackRecommendationResultClick(podId: String, strategyId: String, customerId: String, variationId: String? = null, sectionName: String? = null, resultId: String? = null, numResultsPerPage: Int? = null, resultPage: Int? = null, resultCount: Int? = null, resultPositionOnPage: Int? = null, analyticsTags: Map<String, String>? = null, seedItemIds: List<String>? = null) { | ||
| var completable = trackRecommendationResultClickInternal(podId, strategyId, customerId, variationId, sectionName, resultId, numResultsPerPage, resultPage, resultCount, resultPositionOnPage, analyticsTags, seedItemIds) |
There was a problem hiding this comment.
Adding seedItemIds as a new parameter to the existing trackRecommendationResultClick function changes the JVM method signature and will break binary compatibility for apps compiled against older versions of this library (NoSuchMethodError at runtime) and source compatibility for Java callers. To avoid a breaking change, keep the old signature as an overload (without seedItemIds) delegating to the new implementation (e.g., passing null), and optionally deprecate the old overload.
There was a problem hiding this comment.
I think Copilot has a point here. What do you think about leaving the original function as is and adding an overload?
| fun trackRecommendationResultsView(podId: String, itemIds: Array<String>, numResultsViewed: Int, resultPage: Int? = null, resultCount: Int? = null, resultId: String? = null, sectionName: String? = null, url: String = "Not Available", analyticsTags: Map<String, String>? = null, seedItemIds: List<String>? = null) { | ||
| var completable = trackRecommendationResultsViewInternal(podId, itemIds, numResultsViewed, resultPage, resultCount, resultId, sectionName, url, analyticsTags, seedItemIds) |
There was a problem hiding this comment.
trackRecommendationResultsView(podId, itemIds, ...) gained a new trailing seedItemIds parameter, which changes the JVM method signature and is a binary-breaking change for existing consumers. Consider restoring the previous signature as an overload delegating to this new one (passing null), and optionally deprecate the old overload to guide migration.
| fun trackRecommendationResultClick(podId: String, strategyId: String, customerId: String, variationId: String? = null, sectionName: String? = null, resultId: String? = null, numResultsPerPage: Int? = null, resultPage: Int? = null, resultCount: Int? = null, resultPositionOnPage: Int? = null, analyticsTags: Map<String, String>? = null, seedItemIds: List<String>? = null) { | ||
| var completable = trackRecommendationResultClickInternal(podId, strategyId, customerId, variationId, sectionName, resultId, numResultsPerPage, resultPage, resultCount, resultPositionOnPage, analyticsTags, seedItemIds) |
There was a problem hiding this comment.
I think Copilot has a point here. What do you think about leaving the original function as is and adding an overload?
…ed-item-ids-to-rex-events
There was a problem hiding this comment.
Code Review
This PR adds seedItemIds support to trackRecommendationResultClick and trackRecommendationResultsView events, correctly propagating the parameter through public/internal API layers and request body models, with good test coverage.
Inline comments: 3 discussions added
Overall Assessment:
| fun trackRecommendationResultClick(podId: String, strategyId: String, customerId: String, variationId: String? = null, sectionName: String? = null, resultId: String? = null, numResultsPerPage: Int? = null, resultPage: Int? = null, resultCount: Int? = null, resultPositionOnPage: Int? = null, analyticsTags: Map<String, String>? = null) { | ||
| var completable = trackRecommendationResultClickInternal(podId, strategyId, customerId, variationId, sectionName, resultId, numResultsPerPage, resultPage, resultCount, resultPositionOnPage, analyticsTags) | ||
| fun trackRecommendationResultClick(podId: String, strategyId: String, customerId: String, variationId: String? = null, sectionName: String? = null, resultId: String? = null, numResultsPerPage: Int? = null, resultPage: Int? = null, resultCount: Int? = null, resultPositionOnPage: Int? = null, analyticsTags: Map<String, String>? = null, seedItemIds: List<String>? = null) { | ||
| var completable = trackRecommendationResultClickInternal(podId, strategyId, customerId, variationId, sectionName, resultId, numResultsPerPage, resultPage, resultCount, resultPositionOnPage, analyticsTags, seedItemIds) |
There was a problem hiding this comment.
Suggestion: The completable variable is declared with var but never reassigned — it should be val. This is a pre-existing pattern in the file, but since this PR is touching these lines, it would be a good opportunity to fix it here. Same applies to the two trackRecommendationResultsView overloads below.
// Change:
var completable = trackRecommendationResultClickInternal(...)
// To:
val completable = trackRecommendationResultClickInternal(...)| assertEquals("pdp5", requestBody["pod_id"]) | ||
| assertEquals("User Featured", requestBody["strategy_id"]) | ||
| assertEquals("TIT-REP-1997", requestBody["item_id"]) | ||
| assertEquals("[seed-item-123]", requestBody["seed_item_ids"]) |
There was a problem hiding this comment.
Important Issue: The test asserts "[seed-item-123]" (with brackets) as the serialized value of seed_item_ids. This format is the JSON array representation from Moshi's serialization, stripped of quotes by the getRequestBody helper. While this likely works today due to the parser implementation, the assertion is coupling the test to a specific serialization artefact of getRequestBody.
It would be clearer and more robust to verify this field is present and non-null, and separately test the actual JSON body format. At minimum, a comment explaining why the expected value includes brackets would help future readers understand the intent:
// Moshi serializes List<String> as a JSON array; getRequestBody strips quotes
// so "[\"seed-item-123\"]" becomes "[seed-item-123]"
assertEquals("[seed-item-123]", requestBody["seed_item_ids"])| } | ||
|
|
||
| @Test | ||
| fun trackRecommendationResultClickWithSingleSeedItemId() { |
There was a problem hiding this comment.
Suggestion: The new tests for seedItemIds only exercise the *Internal methods directly. There are no tests calling the public trackRecommendationResultClick or trackRecommendationResultsView overloads (with itemIds: Array<String> and without) with seedItemIds populated. Since the public methods simply delegate to the internal ones the risk is low, but adding at least one smoke-test for a public overload with seedItemIds would make the test suite consistent with how other parameters are tested in this file.
No description provided.