1
0
Fork 0
firefox/docs/rust-components/topic-guides/merino.md
Daniel Baumann 5e9a113729
Adding upstream version 140.0.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
2025-06-25 09:37:52 +02:00

7.3 KiB

Curated Recommendations Client

Fetches personalized content recommendations from the Merino Service. Merino Curated Recommendations API Docs

The API for the CuratedRecommendationsClient can be found in the Mozilla Rust components Kotlin API Reference and Swift API Reference.

Prerequisites

Ensure that {doc}viaduct is initialized during application startup, as it is used for making network requests.

Async

The Curated Recommendations API is synchronous, meaning calling it directly will block the current thread. To mitigate this, consumers should wrap the API in an async implementation.

Importing the Client

:::{tab-set-code}

import mozilla.appservices.merino.curatedrecommendations.CuratedRecommendationsClient
import mozilla.appservices.merino.curatedrecommendations.CuratedRecommendationsRequest
import mozilla.appservices.merino.curatedrecommendations.CuratedRecommendationsResponse
import mozilla.appservices.merino.curatedrecommendations.CuratedRecommendationsError
import MozillaAppServices

:::

Initializing the Curated Recommendations Client

The CuratedRecommendationsClient is initialized using a CuratedRecommendationsConfig object. This includes a required userAgentHeader and an optional baseHost. If baseHost is not provided, the client will default to the production host.

:::{tab-set-code}


val config = CuratedRecommendationsConfig(
    baseHost = "https://merino.services.mozilla.com"
    userAgentHeader = "Mozilla/5.0"
)

val client = CuratedRecommendationsClient(config)


let config = CuratedRecommendationsConfig(
    baseHost: "https://merino.services.mozilla.com"
    userAgentHeader: "Mozilla/5.0"
)

let client = try CuratedRecommendationsClient(config: config)

:::

Fetching Curated Recommendations

The getCuratedRecommendations() method fetches recommendations based on the provided request parameters.

:::{tab-set-code}


val request = CuratedRecommendationsRequest(
    locale = Locale.EN_US,
    region = "US",
    count = 4,
    topics = listOf("business"),
    feeds = listOf("sections")
)

try {
    val response: CuratedRecommendationsResponse = client.getCuratedRecommendations(request)
    println("Received recommendations: $response")
} catch (e: CuratedRecommendationsError) {
    println("Error fetching recommendations: ${e.message}")
}


let request = CuratedRecommendationsRequest(
    locale: Locale.en-US,
    region: "US",
    count: 4,
    topics: ["business"],
    feeds: ["sections"]
)

do {
    let response = try client.getCuratedRecommendations(request: request)
    print("Received recommendations: \(response)")
} catch {
    print("Error fetching recommendations: \(error)")
}

:::

Data Models

Curated Recommendations Request Model

The CuratedRecommendationsRequest model defines the parameters required to request curated recommendations.

Request Fields

Field Type Description
locale string The Firefox installed locale, e.g., en, en-US, de-DE. Determines the language of recommendations.
region string (optional) (Optional) The country-level region, e.g., US or IE. Helps return more relevant recommendations. If not provided, it is extracted from locale if it contains two parts (e.g., en-US).
count integer (optional) (Optional) The maximum number of recommendations to return. Defaults to 100.
topics array<string> (optional) (Optional) A list of preferred curated topics.
feeds array<string> (optional) (Optional) A list of additional data feeds. Accepted values: "need_to_know", "fakespot", and "sections".
sections array<object> (optional) (Optional) A list of section settings that the user follows or has blocked.
experimentName string (optional) (Optional) The Nimbus New Tab experiment name that the user is enrolled in. Used to run backend experiments independently of Firefox releases.
experimentBranch string (optional) (Optional) The branch name of the Nimbus experiment that the user is in.
enableInterestPicker boolean (optional, default: false) (Optional, defaults to false) If true, the API response will include an interestPicker object with sections for interest bubbles.

Curated Recommendations Response Model

The CuratedRecommendationsResponse model defines the response format containing recommendations.

Response Fields

Field Type Description
recommendedAt integer The timestamp (in milliseconds) indicating when the recommendations were generated.
data array<object> A list of curated recommendation items.
feeds object (optional) (Optional) A structured set of multiple curated recommendation lists.
interestPicker object (optional) (Optional) Returned if enableInterestPicker is true in the request. Specifies the display order (receivedFeedRank) and a list of sections (referenced by sectionId) for interest bubbles. The text in these bubbles should match the corresponding section title.

Error Handling

The Curated Recommendations component defines the following error hierarchy:

  • CuratedRecommendationsApiError: Base error
    • Network(reason: string): Network error while making a request.
    • Other(code: integer (optional), reason: string): Generic error containing an HTTP status code and message.

Handling Errors in Kotlin and Swift

:::{tab-set-code}

fun fetchCuratedRecommendations() {
    try {
        val response = client.getCuratedRecommendations(request)
    } catch (e: CuratedRecommendationsError.Network) {
        // Log and retry after 5 minutes
        Log.w("Network error when fetching Curated Recommendations: ${e.reason}")
        scheduleRetry(300)
    } catch (e: CuratedRecommendationsError.Other) {
        when (e.code) {
            400 -> Log.e("Bad Request: ${e.reason}")
            422 -> Log.e("Validation Error: ${e.reason}")
            in 500..599 -> Log.e("Server Error: ${e.reason}")
            else -> Log.e("Unexpected Error: ${e.reason}")
        }
    }
}

func fetchCuratedRecommendations() {
    do {
        let response = try client.getCuratedRecommendations(request)
    } catch CuratedRecommendationsError.Network(let reason) {
        // Log and retry after 5 minutes
        print("Network error when fetching Curated Recommendations: \(reason)")
        scheduleRetry(seconds: 300)
    } catch CuratedRecommendationsError.Other(let code, let reason) {
        switch code {
        case 400:
            print("Bad Request: \(reason)")
        case 422:
            print("Validation Error: \(reason)")
        case 500...599:
            print("Server Error: \(reason)")
        default:
            print("Unexpected Error: \(reason)")
        }
    }
}

:::