Closed article instrumentation for paywall tracking
Marfeel classifies every article into one of three visibility levels that determine content accessibility and user access methods:
- Open: Free for all users.
- Dynamically closed:
Limited access for specific users.
- Metered paywalls: Based on consumption.
- Dynamic paywalls: Based on subscription potential.
- Hard closed:
Exclusive to subscribers.
This visibility setting assists subscription managers and editors in refining the paywall strategy.
Web JavaScript tracking
Section titled “Web JavaScript tracking”Marfeel determines article visibility using the following priority logic:
- If Marfeel receives a hard closed event, the article is considered hard closed.
- If Marfeel does not receive a hard closed event but receives a dynamically closed instrumentation event, the article is considered dynamically closed.
- If Marfeel does not receive any closed event but the article is marked as
isAccessibleForFree = false, the article is treated as hard closed.
Article visibility can be specified via standard structured data or via pageVars as described below.
Closed articles
Section titled “Closed articles”Marfeel automatically detects closed articles based on the isAccessibleForFree structured data field. This field is recommended by Google for SEO, and sites should use it to improve their search positioning. Marfeel reads the same field.
<script type="application/ld+json">{ "@context": "https://schema.org", "@type": "NewsArticle", "isAccessibleForFree": false}</script>To track the number of closed pageviews, instrument these articles with the closed page var:
window.marfeel.cmd.push(['compass', function(compass) { compass.setPageVar('closed', 'hard-paywall');}]);Dynamically closed articles
Section titled “Dynamically closed articles”Articles dynamically closed per user depending on different criteria (like user consumption, pageviews, RFV, or any other metered strategy) must be reported using the closed page var:
window.marfeel.cmd.push(['compass', function(compass) { compass.setPageVar('closed', 'dynamic-paywall');}]);If an article can be dynamically closed for different reasons, the closed page var supports different values. For example, you can report that a pageview was dynamically closed because of a metered signwall strategy:
window.marfeel.cmd.push(['compass', function(compass) { compass.setPageVar('closed', 'dynamic-signwall');}]);Conventionally, pages that are dynamically closed should feature closed page variable values that begin with ‘dynamic-.’ For instance, ‘dynamic-mixed’ indicates that the article experienced both dynamic-paywall and dynamic-signwall.
When an article acquires both hard and dynamic closed data, Marfeel will categorize its visibility as mixed. In this context, ‘mixed’ means an article encountered a hard-paywall along with either of the other two dynamic values.
AMP tracking
Section titled “AMP tracking”AMP pages cannot execute JavaScript directly (e.g., compass.setPageVar(...)), so you must pass the closed value via amp-analytics using AMP variables and macros.
- Ensure required AMP components are included: Add these to the
<head>of your AMP document
<!-- Add the amp-analytics component in the <head> if not present --><script async custom-element="amp-analytics" src="https://cdn.ampproject.org/v0/amp-analytics-0.1.js"></script>
<!-- If you use AUTHDATA(...), ensure your AMP access/subscriptions component is configured --><script async custom-element="amp-subscriptions" src="https://cdn.ampproject.org/v0/amp-subscriptions-0.1.js"></script>
<!-- or amp-access if that's what you use --><script async custom-element="amp-access" src="https://cdn.ampproject.org/v0/amp-access-0.1.js"></script>- Configure amp-analytics with a new
closedvar
<amp-analytics config="https://sdk.newsroom.bi/amp.v1.json" data-credentials="include"> <script type="application/json"> { "vars": { "accountId": "/* AccountId */", "closed": "CLOSED LOGIC" } } </script></amp-analytics>Accepted values for closed (same semantics as web):
hard-paywalldynamic-paywalldynamic-signwall- Any other dynamic reason as
dynamic-* - Empty string for open articles.
Examples
Section titled “Examples”1) Use AUTHDATA from AMP Access / Subscriptions
"closed": "$IF($EQUALS(AUTHDATA(paywallReason),metered),$IF($EQUALS(AUTHDATA(data.isLoggedIn),false),dynamic-singwall,dynamic-paywall),'')"2) Force hard paywall on all AMP pageviews
"closed": "hard-paywall"3) Set based on cookie state (fallback to none)
"closed": "$IF($EQUALS(COOKIE(wall_state),dynamic-paywall),dynamic-paywall,'')"4) Dynamic signwall when user not logged in
"closed": "$IF($EQUALS(AUTHDATA(data.isLoggedIn),false),dynamic-signwall,dynamic-paywall)"5) Open article (default). Omit closed
If the article is open on AMP, either omit the closed var or set it to an empty string:
"closed": ""Note: The examples above are illustrative only. You can compute closed with any AMP macros/substitutions you already use to display the paywall; e.g., QUERY_PARAM(...), AMP_GEO(ISOCountry), CONSENT_STATE / CONSENT_STRING, VARIANT(name) / VARIANTS, CLIENT_ID(scope), DOCUMENT_REFERRER, VIEWER, PAGE_VIEW_ID, or RANDOM.
Some macros resolve asynchronously. If they don’t resolve in time, they may delay or prevent the initial pageview hit.
Notes and requirements
Section titled “Notes and requirements”- Keep all
closedvalues as quoted strings inside the JSON. data-credentials="include"is mandatory to resolveAUTHDATA(...)and read credentials or cookies.- You can use any valid AMP macro (e.g.,
QUERY_PARAM,CLIENT_ID,VIEWER,PAGE_VIEW_ID, etc.).
Troubleshooting (AMP)
Section titled “Troubleshooting (AMP)”csnot showing in network requests?- Check for validation issues or AMP console warnings.
- Ensure macros like
AUTHDATA(...)are resolving properly.
- Empty AUTHDATA response?
- Confirm your
amp-subscriptionsoramp-accessendpoint returns all required fields.
- Confirm your
- Cookies not read?
- Check cookie domain/path compatibility with AMP cache.
Troubleshooting
Section titled “Troubleshooting”Open articles that appear hard-closed
Section titled “Open articles that appear hard-closed”If you have isAccessibleForFree=false because of a dynamic paywall, inform Marfeel by instrumenting dynamic closes. If you already have the implementation in place but still see a hard-close icon, there are two possible causes:
- You are sending both hard closed and dynamic closed events.
- You have
isAccessibleForFree = falseon an article that has never been dynamically closed. In that case, consider removing the isAccessibleForFree flag, as it sends a misleading signal to Google.
Compass not showing the defined visibility
Section titled “Compass not showing the defined visibility”Depending on how you load Marfeel’s SDK, you may get an error when calling the setPageVar tracking code:
(index):354 Uncaught TypeError: Cannot read properties of undefined (reading 'cmd')
Protect against this by initializing the marfeel object before calling it:
window.marfeel = window.marfeel || { cmd: [] };window.marfeel.cmd.push(['compass', function(compass) { compass.setPageVar('closed', 'hard-paywall');}]);Experiences targeting
Section titled “Experiences targeting”On Experience Manager, the closed pageVar can be leveraged as a custom var. This is useful to exclude Experiences from closed articles.
It cannot be used in AMP experiences.
How does Marfeel determine article visibility?
Marfeel uses a priority-based system. If it receives a hard closed event, the article is hard closed. If it receives only a dynamic closed instrumentation event, the article is dynamically closed. If no closed event is received but isAccessibleForFree is set to false, the article is treated as hard closed.
How do I track closed articles on AMP pages?
Since AMP pages cannot execute JavaScript directly, pass the closed value via amp-analytics using AMP variables and macros. Configure the closed var inside the amp-analytics JSON with the same values used on web: hard-paywall, dynamic-paywall, or dynamic-signwall.
Why do open articles appear as hard-closed in Compass?
This typically happens when isAccessibleForFree is set to false for a dynamically paywalled article without sending a dynamic closed event. Either instrument the dynamic close or remove the isAccessibleForFree flag if it sends a misleading signal to Google.