Skip to main content

Recommendations API

Recommendations API

For programmatic access to content recommendations without UI:

import TeadsSDK

class RecommendationsManager {

private var recommendationsPlacement: TeadsAdPlacementRecommendations?

func fetchRecommendations() async throws -> [OBRecommendation] {
// Create configuration
let config = TeadsAdPlacementRecommendationsURLConfig(
articleUrl: URL(string: "https://example.com/article/123")!,
widgetId: "SDK_1",
widgetIndex: 0
)

// Create placement
recommendationsPlacement = TeadsAdPlacementRecommendations(config, delegate: nil)

// Fetch recommendations
let loader = try recommendationsPlacement?.loadAd()
let recommendations = try await loader?()
return recommendations ?? []
}

// Custom UI for recommendations
func createCustomRecommendationView(for recommendation: OBRecommendation) -> UIView {
let view = UIView()

// Add image
let imageView = UIImageView()
if let imageUrl = URL(string: recommendation.imageUrl ?? "") {
// Load image asynchronously
URLSession.shared.dataTask(with: imageUrl) { data, _, _ in
if let data = data, let image = UIImage(data: data) {
DispatchQueue.main.async {
imageView.image = image
}
}
}.resume()
}

// Add title
let titleLabel = UILabel()
titleLabel.text = recommendation.content
titleLabel.font = .systemFont(ofSize: 16, weight: .semibold)
titleLabel.numberOfLines = 2

// Add source
let sourceLabel = UILabel()
sourceLabel.text = recommendation.source
sourceLabel.font = .systemFont(ofSize: 12)
sourceLabel.textColor = .secondaryLabel

// Layout views...

// Configure viewability tracking — required for accurate impression reporting
TeadsAdPlacementRecommendations.configureViewabilityPerListing(
for: view,
withRec: recommendation
)

return view
}
}

Viewability Tracking

warning

Viewability tracking is required for accurate impression reporting. Publishers who skip this step will see incorrect viewability metrics in their dashboard.

Call configureViewabilityPerListing(for:withRec:) for each recommendation view as you add it to your layout. Pass the view that displays the recommendation and its corresponding OBRecommendation:

// Call for each recommendation view once it is in the view hierarchy
TeadsAdPlacementRecommendations.configureViewabilityPerListing(
for: recommendationView,
withRec: recommendation
)

Once configured, the SDK tracks the view and automatically reports viewable impressions to Teads — no additional work is required.

AdChoices compliance

warning

AdChoices compliance is required. Omitting the widget AdChoices icon or the per-item disclosure icon on paid recommendations violates Teads ad serving policies.

Widget AdChoices icon

Your recommendations widget must display a clickable AdChoices icon — a UIButton at least 30×30 pt, positioned above the widget and hidden until recommendations load. When tapped, open the URL returned by TeadsAdPlacementRecommendations.getAboutURL() in Safari or an SFSafariViewController:

import SafariServices

if let url = TeadsAdPlacementRecommendations.getAboutURL() {
let safari = SFSafariViewController(url: url)
present(safari, animated: true)
}

RTB disclosure icon (paid recommendations)

Paid (RTB) recommendations require a per-item disclosure icon overlaid on the thumbnail. Add a UIButton (minimum 30×30 pt) above each recommendation image, hidden by default.

For each recommendation, check shouldDisplayDisclosureIcon(). If it returns true, reveal the button, load its icon from disclosure.imageUrl, and open disclosure.clickUrl on tap; otherwise keep it hidden so it never shows on organic recommendations:

if recommendation.shouldDisplayDisclosureIcon() {
disclosureButton.isHidden = false
// Load recommendation.disclosure?.imageUrl and set it as the button image
// On tap, open recommendation.disclosure?.clickUrl in Safari or an SFSafariViewController
} else {
disclosureButton.isHidden = true
}
tip

To verify your implementation, enable RTB test mode so paid recommendations always appear in responses:

TeadsAdPlacementRecommendations.testRTB = true

Remember to remove this call before releasing to production.