This release adds 4 notable features for engineering teams evaluating rollout.
✓ No known CVEs patched in this version
Topics
+8 more
Summary
AI summarySegment filters can now cross entities (user ↔ company/membership) and trackers re‑evaluate on company switches.
Full changelog
This release lets segments filter across entities: user segments can target company and membership attributes, and company segments can target the people inside them. Segment pages get a faster filter-editing flow to match, and trackers now follow company switches instead of staying frozen on their first evaluation. Under the hood, all segment conditions — runtime and list pages alike — now compile through a single filter builder, and the v2 WebSocket surface gains an end-to-end test harness.
What's Changed
🧬 Segments can filter across entities
User segments can now use company and membership attributes ("users whose company is on the Pro plan"), and company segments can use user attributes ("companies with at least one admin member"). Conditions that span entities bind to the same company relationship: an AND of cross-entity conditions only matches when one membership satisfies them together, not when two different companies each satisfy half. In segment lists a user matches if any of their companies qualifies; in live targeting the conditions evaluate against the company the user is currently active in — so what you preview in the list is what delivery enforces.
🎛️ Faster segment filter editing
Segment list pages get a one-click Add filter flow, condition chips now carry an icon showing which entity the attribute belongs to (user, company, or membership), and the attribute pickers and create/edit dialogs show data-type icons in a more compact layout. The Save filter button also surfaces reliably — including after deleting the last remaining condition, which previously left the view and the saved segment silently out of sync.
📡 Trackers follow company switches
The SDK used to keep a tracker's condition snapshot frozen at first distribution: switch to a company that doesn't qualify and the tracker kept firing, switch into one that does and it never started. Tracker sessions now re-distribute whenever a server-side condition result changes, so the client always evaluates the current rules. Ingestion got honest to match: a report only counts when it matches the exact snapshot the server distributed to that client, reports arriving after unpublish are rejected, and the Users card on tracker analytics now labels each row with the company where the events actually fired — "from B +2" when a user triggered the tracker in more than one company. SDK 0.7.8 carries the client half.
🐛 Fixes
- Company segments with grouped conditions matched every company at runtime. Runtime evaluation didn't recurse into condition groups, so a segment whose conditions were wrapped in a group silently compiled to "no filter" — auto-start rules fired (and hide rules stayed off) for companies far outside the segment, while the segment's company list, which compiled correctly, looked right.
- Mixed-entity OR conditions were evaluated as AND at runtime. Company segment evaluation partitioned conditions into per-entity buckets that all had to match, dropping the OR semantics between them.
- Company lists dropped membership conditions. Offline company queries ignored membership-attribute conditions entirely; they now filter with the same semantics as runtime.
- Search no longer clobbers filters. On list pages, the search box's OR clause could overwrite a condition filter's own top-level OR; the two now combine as independent AND members.
🛠️ Under the hood
Segment evaluation was rebuilt on one compiler so list pages and live delivery can no longer disagree:
common/attribute/filter.tsgains a three-projection builder —createBizUserConditionsFilter(with all / current / none company-scan modes) andcreateBizCompanyConditionsFilter— sharing a membership-anchored condition tree with boolean-simplified fallback branches for rows without memberships. Runtime segment evaluation, offline user/company queries, and list search all ride it.- Tracker ingest validates the report's (content, version) pair against the socket's distributed session and resolves the event id from that snapshot rather than the live Version row, with the publish-state check moved inside the ingest transaction. Batch diffs identify tracker sessions by composite key — they carry no biz session id — and compare tracker payloads so condition changes re-emit.
- The v2 WebSocket gateway gains an e2e harness with coverage batches across flow auto-start, checklists, launchers, banners, announcements, resource center, timers, frequency rules, session recovery, identity verification, and runtime segment evaluation.
Full Changelog: https://github.com/usertour/usertour/compare/v0.8.9...v0.9.0
Weekly OSS security release digest.
The CVE patches and breaking changes that affected production tools this week. One email, every Sunday.
No spam, unsubscribe anytime.
Share this release
About usertour
Usertour is an open-source user onboarding platform. It allows you to create in-app product tours, checklists, and surveys in minutes—effortlessly and with full control.The open-source alternative to Userflow and Appcues
Related context
Beta — feedback welcome: [email protected]