Skip to content

Filtering and Editorial Signals

Overview

Every call to GET /recommend/v1/recommendations runs in two stages:

  1. Pre-personalization filtering — narrow the universe of candidate items down to the slice that is eligible for the request.
  2. Editorial reranking — apply newsroom signals on top of the model’s ranking.

Filtering decides which items are even allowed to compete for a slot. Editorial Signals then decide what is editorially encouraged, discouraged, or required for a given reader to see (or not see). In short: AI decides what is likely to engage a reader; filters and signals let your newsroom shape that output without retraining anything — the changes take effect on the very next recommendation request.

Pre-personalization filters

Scope recommendations to a specific section, content type, or both — before personalization runs — so your readers only see candidates that belong in the placement.

Pre-filters are more efficient than excluding the same items in your own client code: items that don’t match are never scored, never returned, and never compete with matching items for the slot.

The filter dimensions

Query paramRequiredEffect
site_idyesHard partition by website. A single tenant may host many sites; this scopes the catalog.
sectionnoEditorial section (e.g. politics, sports). Restricts to items tagged with that category.
content_typenoContent type (e.g. article, video, podcast). Restricts to items of that type.

Examples

Homepage feed for an anonymous reader on the news site:

GET /recommend/v1/recommendations
?site_id=news.example.com
&user_id=anon-abc-123
&num_results=10

Returns up to 10 items from news.example.com.

Sports section page:

GET /recommend/v1/recommendations
?site_id=news.example.com
&user_id=u-42
&section=sports
&num_results=20

Returns up to 20 items in the sports category.

Video-rail module on the homepage:

GET /recommend/v1/recommendations
?site_id=news.example.com
&user_id=u-42
&content_type=video
&num_results=8

Returns up to 8 video items only.

Politics-section video rail:

GET /recommend/v1/recommendations
?site_id=news.example.com
&user_id=u-42
&section=politics
&content_type=video
&num_results=6

Returns up to 6 politics videos.

Key details

  • No model changes needed. Adjustments to filtering happen at the point of serving recommendations: the underlying model stays completely intact.
  • Content is always scoped to your site. Every request is automatically limited to your site’s catalog.
  • Extra candidates are fetched behind the scenes. The system requests more results than you asked for, so that editorial exclusions and pinned items (see Editorial Signals below) can be applied without leaving gaps in the final response.
  • Filter values must match exactly. Filters look for precise matches only: no partial or fuzzy matching. If your content taxonomy uses nested categories (e.g. sports/nfl/scores), make sure values are fully resolved before sending them.

Query parameters

site_id and user_id are required; num_results defaults to 5 (range 1–50); section and content_type are the optional filters described above. For the full parameter table and the response shape, see the Query Parameters table in the API Developer Guide.

Editorial Signals

Editorial Signals are a layer of human-controlled ranking rules that sit on top of the Recommendations API’s machine-learned recommendations.

They let your newsroom override, nudge, or filter the model’s output at serving time — like filters, they take effect on the very next recommendation request (see Overview).

Signals are exposed through a dedicated service: the Signals API (/signals/v1).

The four signal types

There are four distinct signal types. Each one answers a different editorial question.

Signal typeEditorial questionEffect on the ranked list
Boost”I want this to do better than the model thinks it will.”Multiplies the item’s AI score by a weight between 1.0 and 10.0. Item rises naturally in the ranking.
Bury”I want this to do worse than the model thinks it will.”Multiplies the item’s AI score by a weight between 0.0 and 0.9. Item falls in the ranking but isn’t removed.
Pin”This item must appear at position N.”Moves the item to a specific 1-indexed slot, overriding its ranked position. Applies only to items already in the candidate set — see the caveat below.
Exclude”This item must not appear at all, regardless of relevance.”Removes the item from the candidate set entirely. Takes precedence over every other signal, including Pin.

Boost and Bury are soft — they bias the ranking. Pin and Exclude are hard — they override it. The reranker applies them in a deterministic order (exclude → boost/bury → sort → pin → truncate), so the outcome is predictable no matter how many signals stack up on the same response.

Two ways to drive signals

The Signals API is intentionally agnostic about who is creating signals. That gives you two complementary integration patterns, and most newsrooms will run both at once.

1. Rules-based, automated from the content ingestion process

This pattern produces signals as a side effect of content moving through your CMS or content pipeline. It is best for organization-wide editorial policy: rules that should always be true without anyone clicking a button.

There’s no user interface to manage rules, so implementing these within custom middleware code is required.

For Arc XP customers, that will typically entail extending the content synchronization integration to set Signals during the content ingest/update moment.

Common examples:

  • Always favor staff-bylined content. When a story is ingested with a staff byline, your ingestion worker calls POST /signals/v1/signals with a boost of, say, 1.5. Wire content from outside the newsroom no longer competes on equal footing with staff-produced reporting.
  • Promote breaking news automatically. When the CMS flags a story as breaking, your pipeline opens a boost signal with a higher weight (e.g. 5.0) and a short end_at window — typically 30 to 90 minutes. The story floods every reader’s feed for the duration of the breaking-news window and quietly steps back to AI-only ranking when it expires.
  • Enforce content category policy. Suppress unloved content categories during specific dayparts using a bury with a weight of 0.3 and a scheduled start_at/end_at.

2. Manual, driven by editorial curation tools

This pattern produces signals from a person clicking a button. It is best for moment-to-moment editorial judgment.

Common examples:

  • Highlight a single story. A homepage editor clicks “Pin to slot 1” on a developing investigation. The curation tool calls POST /signals/v1/signals with signal_type: "pin" and position: 1. From that moment on, every reader’s personalized recommendation list opens with that story.
  • Quietly suppress a story. Legal asks for a piece to be pulled from recommendations while a correction is drafted. An editor clicks “Hide from recommendations.” The curation tool creates an exclude signal. The story remains published and linkable, it just stops appearing in any Compass-driven module until the signal is removed.
  • Counter-program the algorithm. A producer notices that the model is over-saturating one beat. They apply a short-lived bury to two or three specific items to rebalance the page in real time.
  • Time-boxed promotion. A live blog or live event needs to dominate the page for the duration of the event. Editorial sets a pin with start_at = event start, end_at = event end. The pin self-removes when the event ends.

What this looks like at runtime

When a reader requests recommendations, the Recommendations API:

  1. Asks the AI model’s top candidates and scores.
  2. Loads every active signal.
  3. Hands the candidate list and the signals to the reranker, which:
    • Drops any item under an active exclude signal.
    • Multiplies each remaining item’s score by its boost or bury weight.
    • Re-sorts by the adjusted score.
    • Moves pinned items to their absolute positions, in ascending position order (and synthesizes a coherent score so the response is internally consistent). A pin whose item is not in the candidate list is skipped.
    • Truncates to the requested page size.
  4. Returns the final list.

No model retraining. No batch job. No cache to bust.

The signal you wrote a second ago is the signal that ranks the next request.

Scheduling

Every signal supports optional start_at and end_at timestamps:

  • start_at — the signal does nothing until this time. Useful for scheduled promotions, or pre-staging top-news rules ahead of a known event.
  • end_at — the signal stops applying at this time without you having to call back to delete it. Critical for breaking-news boosts (which should decay, not linger) and any time-boxed editorial campaign.

A signal with neither field is active immediately and active forever, until explicitly deleted via DELETE /signals/v1/signals/{id}.

Site isolation

All signals are scoped to a single site within your instance. You can boost, bury, pin, and exclude items in the context of one site without impacting any others.

Operational properties

  • No retraining required. Signals are pure post-processing.
  • Bounded volume. The list endpoint returns all matching signals in one response, because the reranker already loads the full set on every recommendation request.
  • Editorial provenance. Every signal records its created_by and created_at timestamp, so it is always possible to audit who applied what override and when.
  • Reversible. Deleting a signal restores pure AI ranking for that item on the next request. There is no “soft delete,” the change is immediate and complete.

When not to use signals

Signals are a precision tool. They are not a substitute for:

  • Removing content from the index — if a story is unpublished, it should leave the content collection through normal CMS lifecycle, not via a permanent exclude signal.

Signals API reference

All endpoints are under /signals/v1 and require tenant-scoped authentication.

MethodPathPurpose
POST/signalsCreate a signal. Body: site_id, item_id, signal_type, optional weight / position / start_at / end_at.
GET/signalsList signals for the tenant. Optional filters: site_id, item_id, signal_type.
GET/signals/{id}Fetch a single signal.
DELETE/signals/{id}Remove a signal. Effective on the next recommendation request.