Capability map

Gillish Node: product & technical brief.

The complete picture of what Node is: three systems in one WordPress plugin, link management, content-structure visualization, and Google + Rank Tracker, plus the better-together bridge into Gillish Cairnstone, the deliberate non-goals, and where Node sits against its competitors. If a feature exists in the codebase, it’s in this document. This page mirrors the in-repo plans/PRODUCT-BRIEF.md; that file stays the source of truth.

Identity#

Gillish Node is a WordPress plugin by the Gillish studio. It combines link management (cloaked redirects, click tracking, affiliate cloaking, A/B testing, auto-linking) with content-structure visualization (an interactive D3.js graph and a pluggable SEO-signal pipeline) and a Google + Rank Tracker system on top.

  • Entry file: gillish-node.php · namespace: Gillish\Node\* (PSR-4, strict types) · asset prefix: gn-
  • CPT: gillish_node · shortcode: [node] · default URL prefix: /node/ (configurable)
  • Requires WP: 6.0+ · Requires PHP: 8.2 (8.4 recommended, enables the native Dom\HTMLDocument parser in the auto-link walker)
  • Architecture: modular, 15 feature modules under src/Modules/ plus the Content Graph under src/Graph/; 13 modules individually toggleable via ModuleRegistry, the rest infrastructure-and-always-on
  • 7 custom DB tables (click log, two auto-link tables, three Google/GSC caches, rank pins), schema-versioned
  • Frontend footprint: zero JS/CSS on public pages by default, everything renders server-side via the the_content filter; redirects run before any template loads
  • Code quality: 0 errors in Plugin Check held as a release-gate invariant; PHPStan level 9; every hook and option key a typed constant
  • Sibling product: Gillish Cairnstone (visual block builder, namespace Gillish\Cairnstone), standalone, but link-aware when Node is also active

The pitch: three systems#

One plugin, three systems that share a CPT, an admin shell, and a brand:

  • Link Management: managed redirects as WordPress posts, click analytics, affiliate cloaking, A/B routing, dynamic per-link rules, and a keyword auto-linker.
  • Content Graph: an interactive D3.js map of the site’s internal-link architecture with a 5-level topical classification, Link Gravity authority scoring, and 14 pluggable SEO-signal detectors.
  • Google + Rank Tracker: service-account GSC + GA4 sync, a 16-month historical backfill, a Search Performance page, and a passive (no-SERP-API) Rank Tracker built entirely on cached GSC data.

No direct competitor combines link management, auto-linking, Content Graph visualization, GA4/GSC integration, and modular SEO-signal detection in a single plugin. That overlap is the defensible position.

  • Cloaked redirect URLs with a configurable prefix; 301 / 302 / 307 per link
  • Tri-state rel resolution, nofollow / sponsored / ugc / noreferrer / open-new-tab resolved per-link → global default → hardcoded fallback
  • Three insertion modes, Synced (attributes resolved from the DB at render time, so one settings change updates every placement instantly), Direct (attributes baked into the HTML, opt-out via class="gn-direct"), and Shortcode ([node id="42"] / [node slug="…"])
  • Link scheduling (start, expiry, expiry action), max-clicks cap, parameter forwarding, sub-ID path tracking with named labels, per-link CSS classes and preferred anchor text
  • Link categories/groups, uncloaked direct-to-destination mode

Click tracking & privacy#

  • Async click logging via wp_schedule_single_event, zero redirect latency
  • SHA-256-hashed IP salted with wp_salt('auth') (one-way); per-field privacy toggles for IP hash, user agent, referer, country, sub-ID, variant, bot flag
  • Configurable retention (30 / 90 / 180 / 365 days or forever) with monthly aggregation before deletion so totals are never lost
  • Bot filtering on logging via a ~1500-pattern bundle, bot clicks stored flagged and filterable out of every analytics query
  • WordPress Privacy API exporter + eraser (GDPR)

Redirect routing & dynamic rules#

Each managed link can carry an ordered, first-match-wins list of dynamic redirect rules. ~20 context variables (country, device, browser, OS, date, time, weekday, total/sub-ID clicks, referer + referer domain, language, logged-in, user role, random, url_param.*, cookie.*) across 18 operators (is/is_not, contains, starts/ends_with, regex, gt/lt/gte/lte, between, in/not_in, is_set/is_not_set, before/after). No rule matches → fall back to the main target URL.

A/B testing#

Engine-level split testing with weighted variants, sticky routing (a visitor keeps the same variant within a session window), bot exclusion so crawlers never skew assignment, a per-variant click breakdown in Link Analytics, an A/B badge on the Manage Links table, and inline variant configuration in the link editor. Pretty Links Pro parity, shipped.

  • SQL-backed keyword index (two tables) with save-time conflict prevention, the index can’t hold a conflicted state, so there is nothing to scan for at runtime
  • Per-keyword match mode (first / all / last / random / none); phrase matching with a {gap:n} token; pillar boost (+15 effective priority)
  • Distribution caps (max per post, per link per post, per paragraph, minimum proximity, intro guard); anchor-quality validator with blocklist and link-name exceptions
  • Hybrid engine, native Dom\HTMLDocument walker on PHP 8.4, DOMDocument fallback on 8.2–8.3, or a legacy regex plan/commit path (user-toggleable); a stripos pre-check skips posts with no candidates before the walker fires
  • Per-post exclusion (editor meta box, click-to-toggle column on every post-type list, and the Auto-Link page panel); broken-destination links auto-excluded at render
  • Sandbox Preview with a per-candidate decision trace; bulk import; Keyword Tester; a 5-tile Link Health dashboard with a cron destination checker; 5 developer filter hooks

Content-structure visualization#

  • Interactive D3.js v7 SVG graph, pan/zoom/drag/fullscreen, radial silo layout, three density presets with animated transitions, directional arrowheads, viewport-aware tooltips
  • Focus mode, silo-focus mode (a cluster plus its one-hop cross-silo bridges), toggleable L1–L5 levels, shortest-path finder, Click Heatmap overlay, draft-visibility toggle, node-position persistence, dark mode
  • 14 pluggable SEO-signal detectors auto-discovered from src/Graph/Elements/*/element.php, detection always runs; the legend only toggles visualisation. Google-dependent detectors hide when GSC sync is off (no empty badges)
  • Link Gravity: iterative authority scoring (PageRank-class internally; the trademark term is never used in the UI)
  • 5-level topical classification (Hub / Pillar / Cluster / Long Tails / Orphan, names customizable); SEO Health Score (0–100, grade A–F) with Top-3 issue chips; a separate Taxonomy Graph; PNG/SVG/CSV export
  • Filter presets; a WP_DEBUG-gated stress generator producing a realistic 1-hub silo plus ~100 signal events across every detector type

Link Builder canvas#

A standalone D3 canvas (deep-linked from the Content Graph, gated on it) for sketching a new silo and committing it as real WordPress drafts. Role-aware nodes, a wizard with collision-free radial layout, snap-to-parent magnetic reparenting with symmetric auto-demote/promote, saved plans + recent batches in one list, JSON export/import for cross-site silo sharing, an opt-in per-batch managed-link wrapper, a depth advisory cap, and a preflight → lock → drafts → skeleton → cleanup lifecycle with one-click whole-batch deletion.

Google GA4 + Search Console#

  • Full GA4 + GSC module, service account OR OAuth, daily incremental cron sync with live progress, a 16-month historical backfill (burst-mode cursor walk with quota-aware pause/retry) and a weekly rollup that compresses >90-day data
  • Graph Enricher: writes per-node GSC/GA4 metrics that every Content Graph element and overlay reads
  • Per-post Google Performance meta box (impressions, clicks, CTR, average position vs. site average)
  • Search Performance admin page, the Link Analytics layout for organic search: 4 summary tiles, a dual-axis daily trend chart, Top Pages + Top Queries, 7/30/90-day ranges, all served from the cached tables (zero API calls per view)
  • Full ~250-entry country filter injected into GSC fetch payloads

Rank Tracker#

A passive rank tracker built entirely on cached GSC data, no SERP API, no per-query billing, no manual keyword entry. Day-1 auto-seed from the existing GSC cache, dual-window snapshots (30-day smoothed + 3-day narrow), an optional pin system, an SE-Ranking-inspired dashboard (position-distribution donut, tabbed time-series, per-keyword drill-down with cannibalization warnings), post-editor delta sparklines, Content Graph rank-mover overlays, and four parallel alert surfaces (admin notice, email digest, webhook, dashboard widget).

Webhooks, anchor-text tags, GeoIP, shorteners, bots#

  • Webhooks: outbound POST on link-health changes and rank-mover events
  • Anchor-text tags: short evergreen tags (current year, copyright spans, post views, read time) expand inside managed-link anchor text, so an anchor like “Best deals [y]” still shows the year. The tag engine moved to Gillish Core in v2.91.30; Node keeps only this anchor-text expansion, active when Gillish Core is enabled
  • GeoIP: 3 providers (Cloudflare header, MaxMind, IP2Location) behind the gillish_node_resolve_country_code filter chain, the signal Cairnstone’s Conditional Content reads when both plugins are active
  • Shorteners: 5 providers (Bitly, Rebrandly, Short.io, TinyURL, YOURLS)
  • Bot detection: a ~1500-pattern CrawlerDetect bundle behind the gillish_node_is_bot filter

Privacy, RBAC, REST, WP-CLI, QR#

  • Privacy/GDPR: WordPress Privacy API exporter + eraser
  • RBAC: a custom-capability system with 5 plugin-specific caps, installed on activation and self-healed every admin request; managed links already auth on gillish_node_manage_links so agency workflows work without manage_options
  • REST: namespace gillish/node/v1 (links CRUD + resolve, public track endpoint, analytics summary/clicks/top-links/geo/referers)
  • WP-CLI: backfill status/start/tick/cancel commands
  • QR codes for any managed link

Architecture overview#

src/Plugin.php is the single hook registry, every add_action/add_filter lives in register_hooks(), so it is the one file to read when tracing how something is wired. The Content Graph is a pluggable pipeline: each SEO signal is a self-contained class under src/Graph/Elements/<id>/element.php, auto-discovered via a filter, with a topological dependency sort , adding or removing a signal never touches the base. Settings are declarative flat-schema arrays rendered by one renderer. The link-rendering pipeline resolves Synced markers on the_content at priority 8; redirects run on template_redirect at priority 1, before any template.

Better together with Gillish Cairnstone#

Cairnstone is the sibling plugin, a Sandbox composer plus a block library. It is fully standalone (its own GeoLite2 database, its own crawler list). When both plugins are active, Node becomes the intelligence hub the Cairnstone design layer calls into, all gated behind class_exists( '\\Gillish\\Node\\Plugin', false ) so a Cairnstone-only install simply skips it:

  • Managed Link Intelligence: a link-bearing Cairnstone block resolves a Node managed-link ID at render time and inherits the post-redirect destination, preferred anchor text, and rel attributes (one-way: Node exposes, Cairnstone reads)
  • Automated Affiliate Disclosure: Node detects when a post contains sponsored Cairnstone-block links and idempotently injects Cairnstone’s Affiliate Disclosure block (FTC compliance for free; per-post and global overrides)
  • Live Link Health Bridge: Cairnstone surfaces Node’s per-link health as an editor badge and polls a compact, cache-bounded health endpoint from the Sandbox

The boundary is deliberate: Node owns the link layer (cloaking, rules, tracking, health, auto-link, graph, GSC/GA4); Cairnstone owns the design layer (Sandbox, blocks, conditional rendering). No service locator, no shared library, no Composer coupling, they compose cleanly when the user owns both, coherent through the shared Gillish design language and the better-together bridges above, while each keeps its own separate admin menu and neither depends on the other.

What Node deliberately does NOT do#

Explicit non-goals, documented so scope debates don’t re-open every release:

  • Affiliate-program management (commission tracking/payouts), a different product category
  • Block library / page design: that is Gillish Cairnstone; Node owns the link layer Cairnstone calls into
  • Conditional content: shipped in Node v2.79–v2.90, extracted to Cairnstone in v2.91; Node still owns the GeoLite2 country signal
  • Regex / wildcard redirect source patterns: “a managed redirect is a WordPress post” is the identity; pattern-matching is Redirection / Rank Math territory
  • Amazon-only product displays: tracked as a competitive gap, depends on a future PA-API module
  • AI / LLM features: deferred indefinitely per a standing decision
  • Multisite / network activation: single-site install only

Competitive landscape#

Node competes in two spaces. In link management + affiliate cloaking (Pretty Links, ThirstyAffiliates, LinkCentral, Lasso, Easy Affiliate) it differentiates with Synced links (no competitor ships the DB-resolved model), the dynamic-rules engine, Content Graph integration, built-in A/B testing, and import/export round-trip with undo. In internal-linking analysis (Link Whisper, Internal Link Juicer, Linkilo, Yoast) it differentiates with the interactive D3 graph, the pluggable 14-detector pipeline, Link Gravity scoring, the SQL-backed auto-link index, five match modes plus {gap:n} phrase matching, and save-time conflict prevention.

Acknowledged gaps: no Amazon PA-API / product-showcase blocks yet (Lasso / AAWP territory, tracked); regex/wildcard redirect patterns are intentionally out of scope (Redirection / Rank Math territory).

Roadmap#

Node is feature-complete and in maintenance. The phase-by-phase build history, the active roadmap (Cairnstone Synergy hooks + REST + Disclosure injector, the 9-competitor migration wizard, competitive-parity closure, Lemon Squeezy licensing, the A/B enhancement backlog), and how the in-repo plans/ corpus is organised are on the Foundation plan page. Active plans live in plans/; shipped work is summarised in plans/DONE-WORK.md. This brief is the elevator-pitch view, the code is the source of truth.