Voyager Bindings

Binding Sources

Every dynamic data source powering Voyager patterns, auto-catalogued from the live block bindings registry.

What are block bindings?

WordPress 6.5 introduced the Block Bindings API — a server-side mechanism for pulling dynamic values into any block attribute without writing custom blocks. Bind a paragraph’s content to post meta. Bind a button URL to a computed CTA. Bind a heading to a Notion property. The block markup stays the same; the value resolves at render.

Voyager extends this with a library of binding sources — each one a discrete data lane with its own caching, fallback logic, and context. Site data, geo, contextual CTAs, Notion, Airtable, analytics, A/B variants, conditional rules, AI-generated content, post meta. Every source lives in its own inc/*-bindings.php file, calls register_block_bindings_source() on init, and becomes available to any pattern via metadata.bindings.

The grid below is self-updating. It reads WP_Block_Bindings_Registry::get_instance()->get_all_registered() at render time, filters to the voyager/ prefix, and parses each source file’s docblock for a human description. Ship a new binding source, it shows up here — no page edit needed.

Live Registry

Registered sources

See it in action

Live pattern examples

Four patterns demonstrating sources that previously had no reference implementation. Each one wires a real binding source to real block markup — the fallback text you see is what renders when the source has no value for the current context.

Airtable

Base

Data Bindings

Case Study

Project Title from Airtable


This paragraph is loaded live from Airtable via the voyager/airtable binding source. The binding matches a row using the current post slug and returns the value of the Summary field — no content is stored in WordPress.

Client name resolves from Airtable

Pipeline: How This Works
  • Table Alias — Each binding references a table by alias (e.g. case-studies), resolved via the Airtable settings tab to a base_id + table_id pair
  • Row Lookup — By default the current post slug is matched against the table filter_property (usually Slug) — set filter_key + filter_value to override
  • Field Resolution — The key arg names the Airtable field to return; scalars pass through, multi-selects become CSV, attachments return the first URL
  • Triple-Layer Cache — In-memory per-request, then transient (4h TTL default), then API call — stays within the 5 req/sec Airtable limit per base
  • Render-Time Resolution — Bindings evaluate on every render; set _voyager_airtable_refresh postmeta to force-bypass the cache on next view

Edit the row in Airtable and the page updates on the next cache expiry — or flush via the Airtable settings tab for instant sync.

Analytics

GA4

Live

Last 30 Days

Traffic at a Glance


Pageviews

0

Sessions

0

Impressions

0

Clicks

0

CTR

0.0%

Avg Position

0.0

Top performing page this period: /

Top search query from Google Search Console

Pipeline: How This Works
  • Portal Aggregator — Portal pulls GA4 + GSC data per site via service account and normalises into a single response
  • Summary Endpoint — WP fetches from the Portal analytics summary endpoint (configured in Orbit settings) using the voyager_portal_api_key option
  • Valid Keys — pageviews_30d, sessions_30d, impressions_30d, clicks_30d, ctr, avg_position, top_page, top_query — one binding per metric
  • Format Layer — Numeric keys get number_format(), ctr appends %, avg_position keeps one decimal — all done server-side before output
  • Cached 4h — Full payload stored in voyager_analytics_data transient for 4 hours (1h on error) — no per-key request fan-out

Numbers update every 4 hours — delete the voyager_analytics_data transient for an immediate refresh.

A/B Test

Variant

Data Bindings

Start Today

Get Started Today


Our team helps you ship faster with proven playbooks.

Pipeline: How This Works
  • Variants String — Each binding takes a pipe-separated list of variant values (e.g. Option A|Option B|Option C) in a single args.variants string
  • Visitor Cookie — First request sets voyager_ab_variant to an MD5 hash (30-day cookie, HttpOnly, SameSite=Lax) — subsequent requests reuse it
  • Deterministic Pick — crc32(hash + test_id) mod variant_count selects an index — same visitor + same test_id always gets the same variant
  • Per-Test Independence — test_id namespaces each experiment — omit it and the hash defaults to md5 of the variants string so identical variant lists share assignment
  • Orbit Attribution — Combine with Orbit lead tracking to measure which variant a converting visitor saw — no third-party A/B tool needed

Clear your voyager_ab_variant cookie and reload to see another variant — the assignment is sticky, not random per-page.

Conditional

UTM

Data Bindings

Personalized

The right message, for the right visitor.


Welcome. This paragraph rewrites itself based on how you arrived and what device you are using — try appending ?utm_source=google to the URL to see the heading change.

Not signed in yet? No problem — read on.

We typically reply within 2 business hours.

Pipeline: How This Works
  • Rule + Value — Each binding takes a rule (utm_source, utm_medium, utm_campaign, device, days, hours, logged_in, post_age, post_type, month) and a value to match against
  • Content + Else — args.content is returned when the rule is TRUE, args.else when FALSE — omit else to fall back to the block default
  • UTM Detection — Reads ?utm_source / utm_medium / utm_campaign from the URL — values are comma-separated lists (google,bing matches either)
  • Time + Device Rules — hours=9-17 (site timezone), days=weekday|weekend|mon,tue, month=jan,feb, device=mobile|tablet|desktop via UA sniff
  • Extensible — Unknown rules hit the voyager_conditional_rule_{rule} filter — register your own (e.g. is_returning_visitor) without forking the plugin

Append ?utm_source=google to this URL to flip the heading — resize to mobile width to flip the body copy. No reload required beyond the URL change.

Usage

A binding is declared on any block attribute via the metadata.bindings field. Pattern markup references a source by name and passes arguments the source understands. At render, WordPress calls the source’s get_value_callback and substitutes the result.

<!-- wp:heading {
  "metadata": {
    "bindings": {
      "content": {
        "source": "voyager/notion",
        "args": { "key": "Title", "filter_key": "Slug", "filter_value": "home" }
      }
    }
  }
} -->
<h2>Fallback heading</h2>
<!-- /wp:heading -->

Every source accepts a key at minimum. Most also accept filters, a postId context, and source-specific options documented in the inline source files. For a deeper walkthrough of one source in action, see the Notion Platform page.