Skip to content

Personalization without a profile

The same user can want terse answers during an incident and detailed explanations while learning a new subject. Both behaviors are real. Neither supports a permanent personality label.

A hidden profile collapses those contexts into identity. Personalize from evidence that is narrow, inspectable, and reversible instead. Use explicit preferences, active goals, current task state, recent interaction choices, and aggregate product behavior. Do not infer age, gender, income, health, ethnicity, family status, or personality types unless the user explicitly supplies a relevant fact and expects it to be used.

Useful adaptation does not require demographic prediction.

Concept map

text
explicit user statement
  -> editable user memory

active goal
  -> bounded goal context
  -> suggestions tied to that goal

recent behavior
  -> local session or thread adjustment
  -> expires unless confirmed

aggregate product events
  -> improve defaults for everyone
  -> no durable visitor identity

forbidden shortcut
  behavior -> hidden demographic or personality profile

The key separation is between adapting an interaction and claiming something about the person.

Use the narrowest signal that works

If the user asks for bullet points in the current thread, format the next answer that way. There is no need to write a permanent preference.

If the user says, "Always show code before explanation," store it in editable user memory. The explicit scope and durable wording justify reuse.

If the user creates a goal to learn database indexing, use it to rank daily reading suggestions. When the goal is completed, stop using it.

If the user repeatedly dismisses proactive check-ins, reduce the proactive default or ask whether to disable them. Do not infer that the user is anxious, busy, senior, or introverted.

This rule keeps the system honest: persist the smallest claim supported by the evidence.

Give behavior a scope and expiry

Every adaptive signal should answer three questions.

Where does it apply? A thread, a feature, a device session, or the whole account.

How long does it apply? One turn, the current thread, a configured retention period, or until the user changes it.

Who can inspect it? The user, an operator through aggregate reports, or only the running component.

A typed record makes those decisions visible:

ts
type AdaptiveSignal = {
  key: "answer_density" | "suggestion_topic" | "nudge_response";
  value: string;
  scope: "turn" | "thread" | "account" | "aggregate";
  source: "explicit" | "goal" | "interaction" | "product_metric";
  expiresAt?: number;
  userEditable: boolean;
};

function mayPersist(signal: AdaptiveSignal) {
  return signal.source === "explicit" ||
    signal.source === "goal" ||
    signal.scope === "aggregate";
}

This is an example policy, not a universal schema. It shows the important distinction: recent interaction can shape the current experience without silently becoming account memory.

Personalization can remain local

Many useful adaptations need no server profile.

The newest reply can keep its suggested choices active while older choices disable. A slide widget can remember its current page only while mounted. A composer can retain a device-local draft. A mini app can use local IndexedDB for state that never needs synchronization.

Local state lowers the consequences of a wrong guess. It also works offline and avoids adding another category to account data.

When synchronization is useful, store the direct setting, not the inference that produced it. Save "compact rows enabled" instead of "power user." Save "notifications off" instead of "notification averse."

Aggregate analytics improve defaults

Product teams still need evidence. Aggregate-only analytics can count page views, feature clicks, goal completions, and outbound actions without building durable visitor profiles.

Respect Global Privacy Control and Do Not Track before reading the body. Exclude cookies, raw queries, URL fragments, form text, DOM text, IP addresses, user agents, and persistent client identifiers. A random tab token can be hashed and used only for expiring session estimates.

Store daily counters and approximate unique tab counts with retention limits. Reports should say "estimated tab sessions" and "best-effort traffic," not users. Public requests can be forged, and a tab is not a person.

Campaign parameters are useful when validated and normalized. They explain which link produced activity without identifying who clicked it.

Aggregate behavior can answer, "Do people use the comparison widget on mobile?" It should not answer, "What kind of person is this visitor?"

Terminology

  • Explicit preference is a user-stated instruction intended for reuse.
  • Behavioral signal is an observed action with a defined scope and lifetime.
  • Adaptive state changes presentation or ranking without asserting identity.
  • Hidden profile is an inferred personal description the user cannot inspect or correct.
  • Demographic inference predicts sensitive or identity-linked traits from behavior.
  • Aggregate metric combines events so individual histories are not retained.
  • Local state stays on the device or in the active component.
  • Reversible personalization can be edited, disabled, expired, or cleared.

These terms keep "personalization" from becoming a blanket justification for collection.

Decisions and rejected alternatives

Prefer explicit settings and goals over inferred traits. They are easier to explain, correct, and retire.

Treat temporary behavior as temporary by default. Repetition alone does not establish durable preference because repeated actions often reflect one project or deadline.

Improve broad defaults with aggregate analytics. This captures product evidence without creating account-level behavioral dossiers.

Make user memory editable. If personalization affects future answers, the user needs a direct correction path.

Rejected alternatives include a model-written personality summary, demographic enrichment from names or language, and a universal engagement score. Personality summaries turn situational behavior into identity. Demographic enrichment creates sensitive claims unrelated to the task. A single engagement score hides which behavior changed and encourages optimization for activity rather than usefulness.

Another rejected alternative is storing raw analytics now and promising to aggregate later. Retention and access controls fail more often than data that was never collected.

Failure modes

  • Incident-time brevity becomes a permanent terse-answer preference.
  • An active learning goal remains in context after completion.
  • A click is interpreted as purchase, satisfaction, or revenue.
  • A tab token becomes a durable cross-day identifier.
  • Campaign reports retain raw query strings.
  • The assistant infers demographic traits from vocabulary or timezone.
  • A user cannot inspect or edit a durable preference.
  • Local presentation state is synchronized without a product need.
  • Clearing analytics removes reports but leaves raw logs or backups.
  • Product optimization rewards more messages instead of fewer successful turns.

Field checklist

Personalization determines what context a turn receives. The next chapter asks which model should process that context, how quotas affect fallback, and how to compare routes with production evidence: Model routing, cost, and quota. The rich interaction signals discussed here begin with Rich replies with plain fallbacks.

Built from field notes on durable software systems.