A technical community needs to know whether a reference page answered a question. It does not need to reconstruct a person from every click, User-Agent token, screen size, and timestamp. The difference is not cosmetic. An event schema creates a retention, access, and consent obligation for every field it collects, so the useful question comes before the tracking question: what decision will this event change?

Begin with a decision

Suppose the team is deciding whether to improve a browser reference page, fix a broken search route, or add a clearer example to a community answer. Those decisions need page type, anonymous route, broad outcome, and time window. They do not automatically need a raw User-Agent, exact IP address, account email, or a sequence of every page viewed.

An illustrative event record might be limited to this shape:

{
  "name": "helpful_feedback",
  "page_type": "explore_article",
  "topic": "webview",
  "outcome": "yes",
  "session_scope": "short_lived_anonymous",
  "consent": "analytics_allowed"
}

The values are examples, not production statistics. The design matters because each field has a narrow purpose. Keep a data dictionary beside the event name, including owner, legal basis or consent dependency, retention period, and the action the report informs.

Prefer a small journey vocabulary

Five events can answer more than a hundred decorative events when they map to real questions:

  • article_viewed: a page was opened, with a coarse page type and topic
  • search_submitted: a search was attempted, with a redacted or bucketed query class
  • example_opened: a code example or compatibility detail was expanded
  • helpful_feedback: a reader gave a yes or no outcome
  • community_post_published: a signed-in author completed a post flow

Do not emit an event for every scroll tick, focus change, hover, or failed pixel impression unless a documented decision requires it. A noisy stream is difficult to interpret and easy to retain forever. For community posts, a publish event should not copy the post body into an analytics system; the post record and the aggregate outcome have different owners and access needs.

Handle browser information at the edge

Browser data can be useful for a compatibility report, but raw strings are usually too detailed for a content-helpfulness report. Normalize the value into a small bucket such as mobile, desktop, embedded, crawler, or unknown. Keep the original header out of the event payload unless a separately approved diagnostic workflow needs it, and redact before storing a fixture.

The distinction can be expressed in code:

const browserContext = classifyForJourney(request.headers.get('user-agent'));
const event = {
  name: 'article_viewed',
  pageType,
  topic,
  browserContext: browserContext.bucket,
  detailStatus: browserContext.detailStatus
};

The function should return a bounded vocabulary and an unavailable state. A value such as chromium-124-windows-10-64bit may look convenient, but it increases uniqueness without necessarily changing the editorial decision. If the report only asks whether an embedded checkout journey is common, embedded is enough.

Make the denominator visible

An aggregate can still mislead when its population is hidden. A report saying “40 percent found the article helpful” needs the number of eligible responses, the time window, the page scope, the exclusions, and whether repeated responses were limited. An illustrative report might say: 24 yes responses out of 30 eligible feedback actions on WebView articles during one UTC week, with no claim about all readers.

Do not turn a small sample into a precise ranking. A page with 2 of 3 positive responses has a different evidentiary weight from a page with 200 of 300. Show counts beside percentages, use ranges when the sample is small, and label estimates as estimates. This also helps editors avoid rewriting a useful article because of a handful of unusual visits.

Give users a real choice

Optional analytics should not be smuggled in through a feature that a reader needs to use the site. Honour consent signals and regional controls where applicable, avoid loading non-essential measurement before the required choice, and provide a clear way to withdraw. A rejection path should still leave the reference library and community reading flow usable.

The privacy page should name the categories of information, the purpose, retention, providers, and available rights in language that matches the implementation. Advertising measurement and product analytics are separate purposes even when the same vendor is involved. Do not describe an event as anonymous if it can be joined to an account, stable identifier, or detailed request log.

Review the event like an API

Before shipping, ask whether every field is necessary, whether a query can contain personal information, whether access is restricted, whether deletion requests cover the derived record, and whether the retention job actually runs. Test opt-out and consent changes in a clean browser. Check that an error path does not send a form body or raw exception containing a URL query.

The editorial rule is to measure the answer a team needs, not the identity of the person who asked. A small, bounded event vocabulary produces reports that are easier to explain, easier to delete, and more useful in a genuine product decision.