Back to Theory
Theory7 min read · June 30, 2026

Competitor Moves, Captured: Context Engines for Creative Intelligence

Competitor intelligence has a 30–60 day relevance window. A context engine with 45-day half-life decay surfaces what matters now, connects competitor moves to creative responses, and lets you query what worked in response.

F
Feather DB
Engineering

Why competitor moves are the hardest context to manage

Competitor intelligence is the most time-sensitive signal in performance marketing. A competitor's new offer, price move, or creative angle has a specific relevance window — roughly 30–60 days in most D2C categories before the market absorbs it and it no longer shapes creative strategy. After that window, the move is historical context rather than active intelligence.

Most teams handle competitor intelligence badly for two reasons. First, they capture it inconsistently — some moves get noticed and noted, others do not. Second, there is no systematic way to make captured intelligence available at brief time without also surfacing 18-month-old moves that are no longer strategically relevant.

Context engines solve both problems. Consistent ingestion pipelines capture competitor moves as they are observed. Short half-life decay (45 days in the default configuration) ensures that old moves fade from retrieval prominence while remaining available if semantically very relevant to a current query. And typed edges connect competitor moves to the creative responses that followed, making the strategic cause-and-effect chain queryable.

What competitor intelligence to capture

Not all competitor activity is worth encoding. The moves that matter for creative strategy are:

  • New offer structures — a competitor launches a trial, changes their pricing model, introduces a bundle. These shift the value proposition landscape and often require a creative response.
  • New creative angles — a competitor pivots from price-based to emotion-based messaging, or adopts a testimonial format that is getting traction. Knowing what angles competitors are testing informs which territory is getting crowded.
  • Claim changes — a competitor makes new performance claims or certifications. These may require your brand to respond with counter-positioning.
  • Platform and placement shifts — a competitor increases YouTube spend or launches a TikTok-first strategy. These signal where audience attention is shifting.
import feather_db as fdb
from feather_db import MetaRecord, ScoringConfig

db = fdb.DB.open("brand_acme.feather", dim=768)

competitor_move = (
    "Rival brand launched 30-day free trial offer on May 15. "
    "Previously required credit card upfront. Facebook and Instagram ads "
    "emphasizing zero-risk entry, targeting subscription lapsed users. "
    "Category: skincare subscription."
)

meta = MetaRecord()
meta.set_attribute("competitor", "rival_brand")
meta.set_attribute("move_type", "offer_structure")
meta.set_attribute("importance", 0.85)
meta.set_attribute("observed_date", "2026-05-15")

db.add(
    id=move_id,
    vec=embedder.embed(competitor_move),
    text=competitor_move,
    namespace="brand::competitors",
    meta=meta
)

The 45-day half-life for competitor intelligence

Competitor moves lose strategic relevance faster than most other marketing context. A free trial launch that was a significant competitive development in May is largely baked into the market by July. Your audience has been exposed to it. Your creative strategy has already absorbed or ignored it. Surfacing it in August with the same confidence as a move from last week is counterproductive — it adds noise to brief context rather than signal.

Feather DB's 45-day half-life configuration for the competitors namespace handles this automatically:

competitor_scoring = ScoringConfig(half_life=45.0, weight=0.45, min=0.0)

# A move from 6 weeks ago (42 days) retains ~56% of its recency score
# A move from 3 months ago (90 days) retains ~10%
# A move from 6 months ago (180 days) retains ~1%

recent_intelligence = db.search(
    embedder.embed("free trial offer competitor response strategy"),
    k=6,
    namespace="brand::competitors",
    scoring=competitor_scoring
)

The brief generator receives recent, high-confidence competitor intelligence. Stale moves are still in the index — they can surface if semantically very close and specifically queried — but they do not compete with fresh intelligence at equal weight.

Connecting competitor moves to creative responses

The most valuable competitor intelligence pattern is not just knowing what competitors did — it is knowing what your brand did in response and whether it worked. Typed edges capture this:

# A competitor move led to a specific creative response
db.link(from_id=creative_hook_id, to_id=competitor_move_id,
        rel_type="responded_to", weight=0.85)

# That creative response was proven by performance data
db.link(from_id=creative_hook_id, to_id=perf_record_id,
        rel_type="proven_by", weight=0.95)

# Context chain retrieval: competitor move -> creative response -> performance
chain = db.context_chain(
    embedder.embed("competitor free trial offer response"),
    k=3, hops=2,
    namespace="brand::competitors"
)
# hop=0: the competitor move
# hop=1: the creative that responded to it
# hop=2: the performance data from that creative

When the same competitor launches a similar move 12 months later, the context chain retrieval surfaces: the original competitor move, the creative response that followed, and the evidence that the response worked. The team does not have to reconstruct the strategic reasoning from memory — the causal chain is in the graph.

Competitive intelligence at brief time

When a new brief is requested in a competitive category, the brief generation pattern queries both the hooks namespace (what worked for the brand) and the competitors namespace (what competitors are doing now) and combines them:

query = embedder.embed(brief_params)

# What worked for the brand
own_hooks = db.search(query, k=5, namespace="brand::hooks",
                      scoring=ScoringConfig(half_life=270.0, weight=0.3, min=0.0))

# What competitors are doing in the relevant category
comp_intel = db.search(query, k=4, namespace="brand::competitors",
                       scoring=ScoringConfig(half_life=45.0, weight=0.45, min=0.0))

# Format both for the brief generation model
context = format_brief_context(own_hooks, comp_intel)

The brief generation model receives: proven hooks from the brand's own history AND the current competitive landscape. The creative strategy output is grounded in both what works and what the competitive environment requires.

FAQ

How does a context engine handle competitive intelligence differently from a document system?

A context engine applies temporal decay (45-day half-life) so recent moves surface ahead of stale ones, importance weighting so significant moves (major offer changes, large creative pivots) rank higher, and typed edges that connect competitor moves to creative responses and performance outcomes. Document systems do none of these.

What half-life should competitor intelligence use?

45 days is the default for most D2C categories. Fast-moving categories (fintech, consumer tech) may benefit from 30 days. Slower categories (luxury, high-consideration purchases) may extend to 60–75 days. The half-life should match the actual shelf life of competitive relevance in the category.

How do you capture competitor intelligence at scale?

The most common pattern is ad intelligence tools (Meta Ad Library, Pathmatics, Semrush) that observe competitor creative. These outputs get summarized and ingested into the competitors namespace with typed edges linking them to any creative responses your brand produced. Human curation of significance (which moves are worth encoding) improves signal quality.

Can the context engine tell you when a competitor move requires a response?

Not directly — it does not generate alerts. But querying the competitors namespace at brief time surfaces active competitive intelligence automatically. The brief generation model can reason about whether the competitive context requires a specific response based on the retrieved competitor moves and the brand's historical response patterns from the graph.