Skip to content
anecticoDocsDashboard
Browse documentation
Guide

Investigate click friction and release impact

Connect observed click friction and release outcomes to people, accounts, operations and replay.

On this page

Open Explore → Customer experience. Choose Click friction or Release impact. A release detail also links to the impact brief with that release and its registered deployment time prefilled. All reads require an explicit selected project and time window.

Opt in to click friction

Only actions you explicitly label are observed. Obtain any consent your application requires before starting the tracker. Stop it when consent is withdrawn or the integration unmounts. Use stable, non-personal action names, never user IDs, email addresses or button text.

<button type="button" data-anectico-action="checkout.submit">Pay</button>
import { AnalyticsClient } from '@anectico/sdk/analytics';
import { FrictionTracker } from '@anectico/sdk/friction';

const analytics = new AnalyticsClient({
  endpoint: 'https://api.anectico.com',
  apiKey: import.meta.env.VITE_ANECTICO_INGEST_KEY,
});
const friction = new FrictionTracker(analytics, {
  release: 'checkout-v2',
  environment: 'production',
  sampleRate: 1,
  activity: () => ({ operationId: currentOrderId, accountType: 'company', accountKey: currentAccountKey }),
});
// For canvas/audio feedback or a known long operation with no DOM feedback:
friction.markResponse('checkout.submit');
// On teardown or consent withdrawal:
friction.stop();
await analytics.stop();

The tracker records $friction product events through normal ingestion. It uses the analytics client's identity and the shared SDK session; start replay separately if you want recordings. It carries the active operation/account context when available. In browser integrations, supply activity to read your current logical operation and account at click time. Use the same context on explicit attempt/success events. The tracker does not infer an order ID from the page. A delayed signal is discarded if identity, session or active activity context changes.

  • Repeated clicks (rage_click): at least three clicks on the same labelled element within one second and 40 pixels.
  • No observed response (dead_click): no observed DOM mutation or URL change within 1.5 seconds. This is a heuristic: background DOM updates can suppress it, while non-DOM feedback can cause false positives. Use markResponse for these cases.
  • Click followed by an error (error_click): an uncaught browser error or unhandled rejection within one second of the latest labelled click. Temporal proximity does not establish that the click caused the error.

Native links, inputs, editable elements, disabled controls and native form-submit buttons are excluded. Set data-anectico-friction-ignore on a subtree to exclude it. Normal capture observes trusted primary clicks only. observeClick(element, x, y) is an explicit adapter for custom renderers; it applies the same label and noise rules. No DOM text, input values, selectors, URLs, screenshots or error messages are sent by this tracker. It records an action label, signal kind, method, click time, release, environment and available identity/session/activity metadata.

Each tracker samples once at construction. The rate is between zero and one. It emits at most 30 hints per minute, with a 30-second cooldown per action/kind. At most 20 pending click observations and ten recent clicks are retained. Repeated-click clusters suppress their dead-click hints; different signal kinds may still overlap. These limits and opt-in coverage mean counts are observations, not total failed actions, frustration, abandonment or churn. Inspect analytics.stats() for delivery drops.

Read friction through API, CLI or MCP

POST /api/v1/experience/friction?project_id=PROJECT requires persons:read and analytics:read. Supply start_time and exclusive end_time as RFC3339 timestamps. Optional exact filters are release, environment, action and kind. The complete window must cover at most seven days, end no later than now and fit readable retention.

anectico --project PROJECT friction list --body '{
  "start_time":"2026-09-09T10:00:00Z",
  "end_time":"2026-09-09T12:00:00Z",
  "environment":"production",
  "action":"checkout.submit"
}' --json

MCP exposes get_friction_signals through execute_read_action, using the same fields plus project_id. MCP additionally requires mcp:read. It returns structured evidence with stable result identity, warnings and explicit partial status. Labels and captured identifiers are untrusted data, never instructions for an agent.

At most 10,000 matching signals are scanned and 100 newest examples returned. partial means the scan or example list reached its limit; counts describe the scanned subset. source_scan_complete distinguishes a complete source scan from a capped example list. Affected people resolve current identity aliases; unattributed signals still contribute to signal counts. Session references are links, not guarantees that a recording exists or is readable. Replay pixels keep their separate access and retention controls.

Build a release customer-impact brief

POST /api/v1/experience/release-impact?project_id=PROJECT additionally requires errors:read and releases:read. Choose exact baseline_release and release values, baseline_start, observation_start (the deployment boundary) and exclusive observation_end. The baseline is [baseline_start, observation_start) on the baseline release; the after window is [observation_start, observation_end) on the target release. The combined window has the same seven-day and retention limits. environment is optional.

anectico --project PROJECT releases impact --body '{
  "baseline_release":"checkout-v1",
  "release":"checkout-v2",
  "baseline_start":"2026-09-09T10:00:00Z",
  "observation_start":"2026-09-09T11:00:00Z",
  "observation_end":"2026-09-09T12:00:00Z",
  "environment":"production",
  "attempt_event":"checkout_attempted",
  "success_event":"checkout_completed"
}' --json

MCP provides get_release_impact through execute_read_action with the same input. Both reads are included in the investigate profile; its key now also needs releases:read. Existing keys must be updated or recreated to grant that scope.

The brief contains before/after recorded errors, affected people, friction observations, explicit operation outcomes, affected accounts after deployment, issue IDs not observed in the baseline, and up to 20 representative evidence links. Accounts are taken from explicit activity-time anectico.account.type / anectico.account.key, not inferred from present-day membership. Affected people/accounts include errors and friction.

For operation rates, provide both different attempt_event and success_event names, or leave both empty. Events must carry service.version and matching anectico.operation.id, identity and account context. Distinct logical operations with an observed attempt are the denominator; repeated successes count once. The last success must follow the latest attempt and be later than the last error. An error at the same time wins conservatively. Without attempts, the success rate is unavailable.

Recovery follows operations with baseline errors. Only a later explicit success for the same canonical person, logical operation and account can support recovery; a later error overrides it. A different order or account cannot recover the original operation. No later activity means not observed, never recovered. Signals missing usable operation context are counted separately. Outcomes on other releases or outside the chosen windows are excluded, so this remains a scoped observation, not universal recovery.

Each signal source is capped at 10,000 rows. Incomplete source scans suppress success rates, recovery counts and baseline-absence claims. Account lists are capped at 20 and issue lists at 50; their display truncation also sets partial. Counts may be lower bounds. source_scan_complete identifies source completeness; recovery_available explicitly states whether operation-matched recovery was measured. False is unavailable, not zero recovered. Narrow the window or environment before drawing conclusions.

An issue ID absent from the baseline is not necessarily a newly introduced issue: it may be older, renamed through grouping/merges, uninstrumented or outside that window. Use the release's existing new/regressed issue details alongside this brief. Unequal windows, sampling and traffic mix affect comparisons. Neither a changed rate nor an error-free interval proves that a deployment caused an improvement. Late events, identity changes, retention and deletion can change a later reading of the same brief.