npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@usertick/snippet

v2.0.2

Published

Usertick — embeddable feedback / survey widget. Proprietary; Usertick UK Ltd.

Readme

Komutların özet kartı Komut Ne yapar Versiyon değişir? npm run dev Watch mode bundle ✗ npm run serve Test server — npm run build Test build + snapshot + preview ✗ npm run build:fast Sadece bundle ✗ npm run previews Sadece PNG yenile — npm run build:release Release snapshot (versiyon aynı) ✗ GitHub Actions → Release Release flow (bump + deploy + publish) ✓

Usertick — Snippet

Embeddable feedback / survey widget. Single <script> tag drops a Shadow-DOM-isolated form onto any site, fully theme-able, no build step required for end users.

Sibling repos:

  • ../dashboard-backend — .NET API, owns Companies/Workspaces/Surveys/Questions and serves the public config the snippet fetches.
  • ../dashboard-ui — Next.js 16 SaaS dashboard where customers design surveys, view responses and manage their workspace.
  • Bundle: zero runtime deps, ~28 KB gzipped target, ES2018
  • Isolation: all UI rendered inside a closed Shadow DOM — host page CSS cannot touch the widget and vice versa
  • i18n: auto language detection from navigator.languages, unified per-field language map or legacy i18n blocks
  • Triggers: 13 built-in trigger types (delay, scroll, exit-intent, custom event, click/hover, idle, rage-click, URL/referrer regex, device…)
  • Question types: 17 built-in (rating, NPS, emoji, CES, ranking, slider, signature, matrix, contact, date, dropdown, file upload, screenshot, …)
  • Skip logic: per-question conditional branching (logic: { if, then } / multi-rule rules + default)
  • A11y: focus trap, ESC to close, ARIA roles, keyboard navigation across all input types

New here? Step-by-step install + commands guide: docs/getting-started.md.

Quick start

One line on the customer's site — replace comp_abc123 with the company id from the dashboard:

<script async src="https://cdn.usertick.com/loader.js" data-id="comp_abc123"></script>

That's it. The loader (~700 B) reads its own data-id, installs a queueable window.Usertick stub for early API calls, and async-injects the main bundle from the same CDN. Nothing else for the customer to edit.

Don't have your company_id yet? In the dashboard, open Settings → Workspace → Install snippet — the page pre-fills the data-id and gives you tab-by-tab copy/paste instructions for HTML, WordPress, React/SPA, Shopify and Google Tag Manager. The same page also opens automatically right after onboarding and after creating a new workspace, so you'll never have to hunt for it.

Bundler / SPA usage

import Usertick from 'usertick/dist/usertick.esm.js';

Usertick.init({ company_id: 'comp_abc123' });
Usertick.on('submit', ({ survey_id, answers }) => analytics.track('survey_submit', answers));
Usertick.trigger('checkout_completed');

Full API reference: docs/config.md §9.


How it works

Loader snippet (paste on site, ~600 B)
        │
        │  installs window.Usertick stub w/ queueable methods
        │  + window._utSettings = { companyId }
        │  + async-injects dist/usertick.min.js (hard-coded CDN URL)
        ▼
Main bundle  (dist/usertick.min.js)
        │
        │  replaces stub with real instance, drains _q queue
        │  ConfigFetcher  →  fetches config.json (with retry + caching)
        │  SurveyMatcher  →  picks the highest-priority survey for current URL
        │  Storage        →  enforces repeat_policy via localStorage + cookies
        │  TriggerManager →  wires up trigger types per survey config
        │  EventBus       →  dispatches open/close/submit/error to Usertick.on()
        │
        ▼
Trigger fires → Widget mounts in closed Shadow DOM
        │
        │  FormRenderer   →  renders questions, manages step navigation,
        │                    resolves skip-logic via logic-resolver
        │  Submitter      →  POSTs answers (with retry on failure)
        │  showSuccess()  →  success screen → auto-close after 3 s

Source layout

src/
├─ usertick.js                 # Public API, queue drain, auto-init
├─ loader-snippet.js           # Tiny standalone loader (built separately)
├─ core/
│   ├─ event-bus.js            # on/off/emit
│   ├─ storage.js              # localStorage + cookie helpers, repeat_policy
│   ├─ survey-matcher.js       # URL/domain matching, priority resolution
│   └─ i18n.js                 # Language detection, unified + legacy resolvers
├─ config/
│   └─ fetcher.js              # GET config.json with retry & cache
├─ triggers/
│   ├─ trigger-manager.js      # Factory + AND/OR mode evaluator
│   ├─ on-load.js              # 13 trigger files, one class each
│   ├─ on-delay.js
│   ├─ on-scroll.js
│   ├─ on-exit-intent.js
│   ├─ on-custom-event.js      # Usertick.trigger() bridge
│   ├─ on-element-click.js
│   ├─ on-element-hover.js
│   ├─ on-form-submit.js
│   ├─ on-idle.js
│   ├─ on-rage-click.js
│   ├─ on-url-match.js         # SPA-aware (history API patched once)
│   ├─ on-referrer.js
│   └─ on-device.js
├─ ui/
│   ├─ widget.js               # Shadow DOM host, mount/show/hide, focus trap
│   ├─ form-renderer.js        # Question dispatch, validation, step nav
│   ├─ logic-resolver.js       # Skip-logic operators + actions
│   ├─ styles.js               # All CSS as a tagged template (themed via CSS vars)
│   ├─ logo.js                 # Powered-by SVG (light + dark)
│   └─ questions/
│       ├─ welcome.js          # 18 question renderers, one file each
│       ├─ rating.js
│       ├─ nps.js
│       ├─ emoji.js
│       ├─ boolean.js
│       ├─ multiple-choice.js
│       ├─ text.js             # textarea + optional screenshot/file pills
│       ├─ dropdown.js
│       ├─ matrix.js
│       ├─ contact.js
│       ├─ date.js             # date / datetime / time
│       ├─ ces.js              # 1–7 difficulty scale
│       ├─ ranking.js          # HTML5 drag + arrow-key reorder
│       ├─ slider.js           # native range + readout
│       ├─ signature.js        # canvas, mouse + touch
│       ├─ screenshot.js       # standalone html2canvas capture
│       └─ file-upload.js      # drag-drop + click-to-browse
└─ submission/
    └─ submitter.js            # fetch + retry + timeout

Question renderer contract

Every renderer is function(question, container, onChange) → getValue.

  • question — the resolved (i18n applied) question config
  • container — the parent <div class="ut-question"> to append into
  • onChange(value) — called whenever the user changes the answer
  • Return value: a getValue() getter the form renderer calls at submit time

This keeps each question type self-contained and lets the form-renderer treat them all uniformly.

Trigger contract

Every trigger is class { constructor(value, onReady); activate(); destroy(); }.

  • value is the per-condition value from the config
  • onReady is the callback that signals "this condition has fired"
  • destroy() must remove every listener / timer it set up

The TriggerManager instantiates one per condition, wires them to AND/OR mode, and emits _onTrigger once the mode condition is satisfied.


Develop

npm install         # esbuild + puppeteer (puppeteer powers preview screenshots)
npm run dev         # esbuild watch mode → dist/usertick.min.js
npm run build       # TEST build: bundle + dist/test/ snapshot + dist/test/previews/ PNGs
                    #            (version stays the same — safe to re-run)
npm run release     # RELEASE build: bumps package.json version (patch +1),
                    #                snapshots to dist/v<version>/ + dist/v<version>/previews/
npm run build:fast  # bundle only, skip snapshot + previews (fastest)
npm run previews    # regenerate test previews against the current dist/
npm run serve       # static dev server on http://localhost:3000

After serve, browse:

Build output

dist/
├─ usertick.min.js              ← latest bundle (always rebuilt)
├─ usertick.esm.js
├─ loader.js
├─ test/                        ← npm run build target — overwritten on every run
│  ├─ usertick.min.js   usertick.esm.js   loader.js
│  ├─ manifest.json             { version, is_test: true, built_at, file sizes }
│  └─ previews/                 30 PNGs, overwritten
│     └─ q-rating.png   q-nps.png   q-emoji.png   …   manifest.json
└─ v1.0.3/                      ← npm run release target — permanent archive
   ├─ usertick.min.js   usertick.esm.js   loader.js
   ├─ manifest.json             { version, is_test: false, built_at, file sizes }
   └─ previews/                 historical screenshots committed alongside the snapshot
      └─ q-rating.png   …   manifest.json

| File | Format | Use | |------|--------|-----| | dist/usertick.min.js | IIFE | Snippet target — what the loader injects | | dist/usertick.esm.js | ESM | import Usertick from '…' for SPA / bundler users | | dist/loader.js | IIFE | The tiny loader stub itself, ready to paste |

The build script enforces gzipped size budgets: 60 KB for the main bundle, 0.5 KB for the loader. Going over fails the build.

Release flow

npm run dev          → iterate
npm run build        → test build (version unchanged, dist/test/ + dist/test/previews/)
                       inspect the PNGs and the snapshot
npm run release      → bumps version, archives to dist/v<new>/ + dist/v<new>/previews/
git commit && push

Configuration

Full reference: docs/config.md.

config.json
├─ company_id, allowed_domains
└─ workspaces[]
    └─ surveys[]
        ├─ url_rules         (path_prefix / regex)
        ├─ trigger           (mode: any|all, conditions[])
        ├─ repeat_policy     (cooldown_days, max_displays, after_submission)
        ├─ position          (bottom-right | bottom-left | top-* | center-modal)
        ├─ display_mode      (all | steps)
        ├─ branding          (show_logo)
        ├─ theme             (general + light + dark CSS variables)
        ├─ texts + i18n      (per-language UI strings)
        └─ questions[]
            ├─ id, type, label, required
            ├─ logic         (skip-logic: if/then or rules[]/default)
            └─ … type-specific fields

Roadmap

The full product roadmap (analytics, AI probing, bug reporter, session replay, integrations, GDPR/KVKK enterprise mode, etc.) lives in docs/roadmap.md.

Phase 1 is implemented in this repo:

  • 1.1 Conditional / skip logic — see src/ui/logic-resolver.js
  • 1.2 Extra question types (CES, ranking, slider, signature) — see src/ui/questions/
  • 1.3 Advanced triggers (custom event, element click/hover, form submit, idle, rage click, url/referrer match, device) — see src/triggers/

Phase 2+ (analytics dashboard, AI probing, integrations, A/B test, hosted survey, …) are not yet implemented in the snippet — they require backend work.


Release & deployment

Internal release runbook (Cloudflare R2 + CDN + public scoped NPM): docs/publishing.md.

.github/workflows/release.yml is the manual GitHub Action that does the full release in one click — version bump, commit + tag, S3 upload, CloudFront invalidation, Cloudflare cache purge, and npm publish to the private @usertick scope.

License

Proprietary. Copyright © 2026 Usertick UK Ltd. All rights reserved. See LICENSE.

This is a private internal repository. The compiled bundle served from cdn.usertick.com is licensed solely for embedding on customer sites under an active Usertick subscription. Source code, build tooling and documentation are confidential.

For licensing or commercial enquiries: [email protected].