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

tracklint

v0.7.0

Published

Conversion-tracking integrity linter — fail CI when a form or CTA isn't wired for tracking (submit button, dataLayer.push, noindex thank-you page). Zero-dependency, language-agnostic, runs in CI.

Readme

tracklint

tracklint fails CI on a non-button submit control and an indexable thank-you page

Part of a set of zero-dependency CI tools for AI-agent repos — start with reflint.

Did a redesign quietly stop your form from tracking conversions? A conversion-tracking integrity linter. It reads your HTML/JSX source and fails the PR (exit 1 + inline annotations) when a form or CTA isn't wired for tracking. Zero-dependency, language-agnostic, runs in CI.

その改修、フォームのコンバージョン計測を静かに壊していませんか? 送信ボタン・フォーム・サンクスページが計測に 配線されているか を CI で検証するリンタ。表示は正常なのに計測だけ壊れる—を PR 時点で落とす。依存ゼロ・言語非依存。


Why / なぜ

Conversion tracking is the one layer that looks fine when it breaks. A redesign turns a <button type="submit"> into a <div>, the GTM click trigger silently stops firing, unit tests still pass, visual review misses it — and nobody notices until the numbers don't add up months later (sometimes they even go up, because a thank-you page with no noindex double-counts). Runtime QA tools (ObservePoint, Trackingplan, browser debuggers) only catch this after it ships. tracklint checks the source, so it fails the build before merge. It checks facts, not prose — so it works in any language.

Use as a GitHub Action / CIで使う(定着の本体)

# .github/workflows/tracklint.yml
name: tracklint
on: [push, pull_request]
jobs:
  tracklint:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: hyuga611/tracklint@v0  # auto-detects files containing <form>

Findings show up as inline PR annotations, and the job fails (exit 1).

A failing job does not by itself stop a merge — GitHub only blocks one when the check is required, under Settings → Rules (or branch protection). Until you do that, this is a red X somebody can click past. Marking it required is the step that turns it into a gate.

Use as a CLI / ローカルで使う

npx tracklint                 # <form> を含むファイルを自動検出
npx tracklint src/ pages/     # ファイル/ディレクトリ指定も可

What it catches / 検出するもの

| rule | severity | 何を落とすか | |---|---|---| | submit-not-button | error | 送信コントロールが <div> / <span> / <a> で、JS でフォームを submit している → クリック計測が要素を特定できない | | submit-missing-tracking | error | 送信ボタンに一意の id も計測属性(data-gtm-event 等)も無い | | submit-duplicate-id | error | 送信ボタンの id が重複 → クリックの二重計上/取り違え | | submit-dynamic-id | warn | id がテンプレート展開 → 実行時の値・一意性を静的に検証できない | | ajax-no-conversion | warn | AJAX 送信なのに成功時の dataLayer.push / gtag / analytics.track が無い | | thankyou-unresolved | error | フォームのサンクスページがリポジトリに存在しない | | thankyou-indexable | error | サンクスページに noindex が無い → インデックス漏れ・CV 二重計上 |

Exit code 1 when any error is found = a CI gate.(warn は既定では CI を落としません)

鳴らさない条件 / When these rules stay silent

配線系のルール(submit-missing-tracking / submit-missing-gtm-event-attr / ajax-no-conversion)は、 次のどちらかに当てはまるとき黙ります。公開リポジトリ 1,380 本に当てた監査の結果、 この2つが誤検知のほぼ全てだったためです(v0.4.0)。

  1. 計測基盤がプロジェクトのどこにも無いとき。GTM / gtag / fbq / analytics.track 等が 対象ファイルのどれにも出てこなければ、そのリポジトリは計測していない=「計測漏れ」を 指摘する意味がない。GTM は共通ヘッダ側に置かれることが多いので、判定は対象ファイル全体で行う。 この理由で黙ったときは CLI がその旨を出力する(黙った理由が分からないのが一番困るため)。
  2. 連絡先を集めていないフォームのとき。検索・絞り込み・並び替えのフォームはコンバージョンではない。 判定はボタンの文言ではなく入力欄で行う(「空室を検索」のような本物の CV を取りこぼさないため)。 type=email / type=tel / textarea / name・placeholder が連絡先を示す欄があれば対象。

Config / 設定(任意)

tracklint.config.json をリポジトリ直下に置くと上書きできます(無くても動きます)。

{
  "trackingAttributes": ["data-gtm-event", "data-track"],
  "conversionCalls": ["dataLayer.push", "gtag", "analytics.track"],
  "rules": {
    "ajax-no-conversion": "error",
    "submit-missing-gtm-event-attr": "warn"
  }
}

Presets / プリセット(WordPress・Meta Pixel)

フォームフレームワークや計測基盤ごとに「正しい配線」の形は違います。プリセットを有効化すると、その知識に基づく追加ルールが入り、同時に フレームワーク特有の誤爆を抑制 します(例: Contact Form 7 は既定でサンクスへ遷移しないので thankyou-* を出さない)。各完了シグナルは公式ドキュメントで裏取り済み。

// tracklint.config.json
{ "presets": ["wordpress", "meta"] }
npx tracklint --preset=wordpress,meta        # CLI でも指定可("=" と "," 区切り)

wordpress

| プラグイン | 検出 | 完了シグナル | 検証 | |---|---|---|---| | Contact Form 7 | form.wpcf7-form | wpcf7mailsent(成功時のみ発火) | ✅ 完了イベントに計測が配線されているか | | Snow Monkey Forms | form.snow-monkey-form | smf.complete | ✅ 同上 | | WPForms | form.wpforms-form | 確認タイプ3種で可変 | 🔍 検出のみ(誤爆抑制) | | MW WP Form | .mw_wp_form / submitSend | 完了画面 or 別URL | 🔍 検出のみ(誤爆抑制) |

CF7 / Snow Monkey は「送信完了で別URLへ遷移しない」ため、<button> のクリック計測ではなく 完了イベントに計測を配線 するのが正解です。tracklint はこれを検証し、逆にクリック計測ルール(submit-*)を課しません。WPForms / MW WP Form は完了がサーバ再描画・設定依存で静的に確定できないため、検出(=サンクス誤爆の抑制)のみ にとどめます(正直に success-tracking は課しません)。

| rule | severity | 何を落とすか | |---|---|---| | wp-form-no-success-tracking | warn | CF7/Snow Monkey で、完了イベントのリスナ内に計測(gtag / dataLayer.push / fbq)が無い | | wp-form-tracking-on-wrong-event | warn | CF7 で CV を wpcf7submit(無効送信・スパムでも発火)に紐付けている → CV 水増し |

meta

fbq(...) をコンバージョン呼び出しとして認識し、静的に確定できる破損だけを検出します。

| rule | severity | 何を落とすか | |---|---|---| | meta-pixel-track-without-base | error | fbq('track', …) があるのに base code(fbq('init') / fbevents.js)が無い → 送信されない | | meta-pixel-duplicate-init | warn | 異なる Pixel ID で fbq('init') が複数 → PageView/CV の二重計上 |

Meta Pixel の 実発火(本当に CompleteRegistration が飛んだか)は静的には見えません(--runtime は Roadmap 参照)。GTM 経由でのみ設置している場合、生 HTML に fbq が現れないため検出対象外です(誤って「未設置」とは判定しません)。

サンプル: examples/wordpress/cf7-bad.html / cf7-good.html / meta-pixel-bad.html

What this can and cannot see / できること・できないこと

これは 静的解析 です。「配線が存在し正しく書かれている」ことを検証しますが、GTM/GA4 が実行時に実際に発火したことは保証しません。以下は構造的に見えないので、warn/info に留めるか設定で抑制します。動的検証(E2E)は置き換えではなく補完です。

  • GTM のコンテナ側(UI)だけで組んだトリガーは見えない(ページ側に手掛かり=id/属性があるかだけを見る)
  • 別ファイル/バンドル/フレームワークのハンドラに配線された計測は追い切れない
  • CMS やサーバーテンプレートが実行時に注入する dataLayer.push は静的ソースに無い
  • HTTP ヘッダ(X-Robots-Tag)で付けた noindex<meta> が無いと拾えない
  • robots.txtDisallownoindex とは別物(クロール禁止であってインデックス禁止ではない)

Roadmap

  • [x] Static core: submit control / tracking hook / AJAX conversion / thank-you page — zero-dep (src/scan.mjs)
  • [x] GitHub Action (action.yml) + inline PR annotations + self-CI dogfood
  • [ ] --runtime mode (Playwright): 実際に送信してイベント発火とサンクス遷移を検証
  • [ ] SARIF 出力(GitHub code-scanning 連携)
  • [ ] baseline/allowlist(既存リポは新規違反だけで落とす)
  • [x] presets: wordpress(Contact Form 7 / Snow Monkey Forms / WPForms / MW WP Form)+ meta(Meta Pixel)
  • [ ] presets: Shopify / HubSpot

Dev

node --test                 # unit tests
npm run poc                 # 壊れたサンプルで検出デモ → exit 1
npm run selfcheck           # 正しいサンプルの自己検査 → exit 0

Related tools

Zero-dependency CI linters for repos where AI agents do the work. Each one fails the PR on something that breaks quietly.

| | Catches | | --- | --- | | reflint | AGENTS.md / llms.txt / CLAUDE.md pointing at commands, scripts, or paths that no longer exist | | skills-lint | SKILL.md broken references + name/trigger collisions between skills | | carrylint | Skills with the author's machine or model baked in — absolute paths, undeclared CLIs, unresolved placeholders | | genchi | Agents reporting "done" without re-fetching real-world state | | tracklint ← you are here | Forms and CTAs that quietly stopped being wired for conversion tracking | | tokenlint | Hardcoded colors that bypass your design tokens | | reflint for VS Code | The same reflint checks, inline in the editor as you save | | orogami | Not a linter — natural Japanese/CJK line breaking for OGP images (BudouX + font subsetting) |

MIT