Install
No release zip yet. The repository archive installs, but the folder name will carry the branch suffix and updates will not flow:
wp plugin install https://github.com/imranhsayed/naviga/archive/refs/heads/main.zipReadme
Naviga
A WordPress plugin that integrates Naviga Engage with WordPress so Engage's metered paywall, register wall, and premium wall can run on top of WordPress content.
This plugin does not implement metering, paywall UI, or article counting. Engage does all of that itself. The plugin's only job is to drop the Engage loader on every page, tell it which post is being viewed, and provide a header CTA shortcode that shows the right sign-in / subscribe / account links based on the visitor's auth state.
What the plugin does
plugins/naviga/
├── naviga.php # boots the plugin
├── traits/trait-singleton.php
├── includes/
│ ├── Loader.php # prints loader.min.js + MG2Loader.init() in wp_footer
│ ├── Links.php # filterable map of Subscribe / Auth0 URLs
│ └── Cta.php # [naviga_cta] shortcode + styles
└── assets/css/cta.css # CTA visibility per body state class
Engage vs Subscribe
| Naviga Engage | Naviga Subscribe | |
|---|---|---|
| Role | Paywall + audience engagement | Commerce + customer lifecycle |
| Owns | Meter rules, bucket logic (Free / Metered / Premium), paywall HTML templates, campaigns | Offers, subscriptions, entitlements, billing, customer accounts |
| Integration | JS loader dropped on every page | Hosted checkout pages + REST APIs |
Runtime flow:
- Visitor reads articles → Engage counts them.
- Limit hit → Engage paints the Subscribe Wall (CTA links to Subscribe checkout).
- User signs in via Auth0, picks an offer, pays. Subscribe creates the subscription.
- User returns → Engage checks entitlements, fires
onHasAccess, routes user to Free bucket.
How Engage works
Engage is configured entirely in the Engage admin — meter rules, paywall templates, variable sets. The split of responsibilities:
| Engage admin (cloud) | This plugin (site) |
|---|---|
| Meter rules (Free / Metered / Premium) | Loading loader.min.js |
| Article vs section URL patterns | Calling MG2Loader.init(...) with tenant codes |
| Free article limits per user state | Telling Engage the current article ID |
| Paywall HTML templates | Classifying the page via window.pageTag |
| Campaigns, Conversations, Actions | Reacting to authorization events |
Three buckets
Every pageview is sorted into exactly one bucket:
- Free — content is shown, no gate
- Metered — counts against the visitor's monthly quota; when exceeded, a paywall shows
- Premium — gated immediately for non-subscribers
window.pageTag
The plugin emits window.pageTag on single posts so Engage's "JS Var" meter rule qualifier can classify the page. Default is 'metered' for all single posts. Override per post via the naviga_page_tag filter:
add_filter( 'naviga_page_tag', function ( $default ) {
if ( ! is_singular( 'post' ) ) {
return $default;
}
if ( get_post_meta( get_the_ID(), '_is_premium', true ) ) {
return 'premium_locked';
}
if ( get_post_meta( get_the_ID(), '_is_registration', true ) ) {
return 'registration_locked';
}
return $default; // 'metered'
} );
Valid values: 'metered', 'premium_locked', 'registration_locked', 'not_metered'.
Session pre-paint
A synchronous <head> script reads the Auth0 session cookie (auth0_sub by default) and stamps either naviga-state--anonymous or naviga-state--registered on <html> before first paint — eliminating the flash of anonymous CTAs that signed-in users would otherwise see. Engage's event handlers refine the state later (e.g. upgrade to subscribed once entitlements are checked).
Setup
-
Place the plugin in
wp-content/plugins/naviga/. -
Activate it (
wp plugin activate navigaor via the WP admin). -
Create the
/auth0-redirect/page — a plain WordPress page with slugauth0-redirect. Content can be empty; the page just needs to render so Engage's Auth0 SDK can complete the token exchange. -
Configure tenant values via the
naviga_init_configfilter:add_filter( 'naviga_init_config', function ( $config ) { $config['environment'] = 'stage'; // or 'prod' $config['debug'] = WP_DEBUG; $config['auth0'] = [ 'clientId' => '<Auth0 application client id>', 'domain' => '<Auth0 custom domain, e.g. auth.example.com>', ]; $config['engage'] = [ 'clientCode' => '<your client code>', 'siteCode' => '<your site code>', 'configCode' => '<your config code>', 'attr' => '<market code>', // optional — omit if not market-scoped 'settingsKey' => '<market settings key>', // optional — must match variable set in Engage admin ]; $config['fingerprint'] = [ 'version' => '<your version>', ]; $config['g2Insights'] = [ 'collectors' => [ 'connext' ], 'containerId' => '<GTM container id>', 'tagManager' => 'GTM', 'version' => '<your version>', ]; return $config; } ); add_filter( 'naviga_loader_cdn_url', function () { return 'https://cdn.q0losid.com/stage/<version>/loader.min.js'; } ); -
In Auth0, add the redirect URL to "Allowed Callback URLs":
https://example.com/auth0-redirect/https://staging.example.com/auth0-redirect/(etc.)
-
In Engage admin, ensure:
- An active meter set with rules covering the user states above.
- A campaign with Metered and Premium Conversations + Actions.
- Variable sets for each market code you use.
- URL patterns so Engage knows which URLs are articles.
-
In the theme, add the CSS class your Engage Actions target to the article content wrapper, e.g.:
<article class="entry-content article-content__content-group">If the selector doesn't match, Engage logs
ERROR <<<< | <selector> not foundand silently skips rendering the paywall.
Header CTA — [naviga_cta]
Drop the shortcode anywhere a Sign In / Subscribe / My Account / Sign Out group makes sense. All four links are rendered every time; CSS hides the ones that don't apply to the current visitor.
<html> class |
Visible links |
|---|---|
naviga-state--anonymous |
Sign In, Subscribe |
naviga-state--registered |
Subscribe, My Account, Sign Out |
naviga-state--subscribed |
My Account, Sign Out |
Override the URLs via the naviga_links filter:
add_filter( 'naviga_links', function ( $links ) {
return [
'signin' => 'https://auth.example.com/login',
'signout' => 'https://auth.example.com/logout',
'subscribe' => 'https://mycheckout.example.com/',
'account' => 'https://mycheckout.example.com/account',
'activate' => home_url( '/activate/' ),
];
} );
The /auth0-redirect/ page
Auth0 uses the OAuth 2.0 authorization code flow. After authentication, Auth0 redirects to a pre-registered URL on your site with ?code=...&state=.... Engage's bundled Auth0 SDK reads those parameters, exchanges the code for tokens, drops the auth0_sub cookie, and bounces the user back to the page they came from.
Requirements:
- The URL must exist on the WP site (404 breaks login).
- The URL must be whitelisted in Auth0 under "Allowed Callback URLs".
Override the path via naviga_auth0_redirect_path (default /auth0-redirect/).
Filters reference
| Filter | Default | Purpose |
|---|---|---|
naviga_init_config |
Empty tenant values | Full Engage / Auth0 / GTM config |
naviga_loader_cdn_url |
'' (must be set) |
CDN URL for loader.min.js |
naviga_links |
Placeholder # hrefs |
Subscribe / Auth0 / account URLs |
naviga_page_tag |
'metered' on single posts, null elsewhere |
Per-page Engage bucket classification |
naviga_auth0_redirect_path |
/auth0-redirect/ |
Auth0 callback path on this site |
naviga_session_cookie |
auth0_sub |
Cookie name for session pre-paint |
Verifying the integration
Open DevTools on a single post and check:
- Network:
loader.min.jsreturns 200. - Console:
window.pageTagreturns'metered'(or the value you set) on a single post;undefinedmeans no metered rule will match. - Console: one of the
[Naviga] onXxxlog lines fires, confirming the user's bucket. - Engage Debug Panel (visible when
debug: true): shows Meter Level: Metered and a numeric limit.unlimitedmeans the page wasn't classified — see step 2. - Trigger the meter: open more metered articles than the configured limit in a fresh anonymous session. The next metered article should render the paywall.
Troubleshooting
| Symptom | Cause | Fix |
|---|---|---|
Meter limit shows unlimited |
window.pageTag not set |
Confirm is_singular('post') is true; check the naviga_page_tag filter |
Paywall event fires but <selector> not found |
Engage Action CSS selector missing from DOM | Add the expected class to the theme's article wrapper, or change the selector in Engage admin |
| Paywall shows for subscribers | onHasAccess not received, or attr/settingsKey mismatch |
Check Auth0 cookies, check Engage admin variable set codes match your config |
No MG2Loader / loader 404 |
CDN URL wrong or unset | Set naviga_loader_cdn_url filter |
References
- Engage docs: https://docs.navigaglobal.com/engage/-MGi9-KKLwnWfoD36Ot6
- Initialization script setup: https://docs.navigaglobal.com/engage/-MGi9-KKLwnWfoD36Ot6/getting-started-with-engage/configuring-engage-on-your-website/setting-up-the-inititalization-script
- Meter rules: https://docs.navigaglobal.com/engage/-MGi9-KKLwnWfoD36Ot6/fundamentals/meter-rules
- Engage events: https://docs.navigaglobal.com/engage/-MGi9-KKLwnWfoD36Ot6/fundamentals/engage-events
- Subscribe APIs: https://docs.navigaglobal.com/naviga-subscribe/additional-resources/subscribe-apis/subscribe-api