Table of Contents
Introduction and Overview
API Documentation
JavaScript Library Documentation
iMoneza provides a client-side JavaScript library to enhance the paywall user experience.
Implementation
The JavaScript library should be embedded into each individual page that needs to be managed by iMoneza. This is not necessary, however, if you choose to do server-side redirection only.
Insert the script https://cdn.imoneza.com/paywall.min.js
in the head of the document. Then, add additional configuration options and an init()
call in a script block afterward.
For example.
<head>
<title>Our Website</title>
<script src="https://cdn.imoneza.com/paywall.min.js"></script>
<script type="text/javascript">
iMoneza.paywall.init('b865156f-9e0d-48b6-a2a0-097456f689ec', {});
</script>
</head>
Please note: Do not forget to add your domain to the Allowed Origins setting in your Resource Access API Key definition. If you do not do this, you will get a cross-domain JavaScript error and the script will not work.
init
Method
The iMoneza.paywall.init
method initializes the iMoneza paywall. There are two parameters passed to the method. The first is a Resource Access API key. The second is a list of custom configuration options for the page. The custom configuration options will override any settings defined on the Paywall Settings page.
The PaywallSettings object represents the customizable fields a Merchant can define using Paywall Settings. All dates are serialized and are in UTC format (YYYY-MM-DDThh:mm:ssTZD). The full list of custom configuration options that can be passed in looks like:
PaywallSettings Object (and javascript functions)
{
"resourceKey": "",
"resourceURL": "",
"desktopPaywallType": "",
"mobilePaywallType": "",
"mobileMaxWidth": 0,
"embeddedAdBlockerDetection": {
"element": "",
"zIndex": 0,
openWarning: function (title, message) { },
closeWarning: function () { },
openDialog: function (title, message) { },
closeDialog: function () { },
onWarningOpened: function (title, message) { },
onWarningClosed: function () { },
onDialogOpened: function (title, message) { },
onDialogClosed: function () { }
},
"embeddedPaywall": {
"element": "",
"cover": {
"backgroundColor": "",
"visibleHeight": 0,
"visibleHeightMode": "",
"zIndex": 0
},
"frame": {
"zIndex": 0
},
"icon": {
},
open: function (url, isAdSupported, adSupportedMessageTitle, adSupportedMessage) { },
updateHeight: function (heightData) { },
close: function (url) { },
onOpened: function () { },
onHeightUpdated: function (heightData) { },
onClosed: function () { }
},
"embeddedWallet": {
"element": "",
"zIndex": 0,
"adSupportedMessage": "",
"badConfigMessage": "",
"freeMessage": "",
"denyMessage": "",
"propertyUserMessage": "",
"purchaseMessage": "",
"quotaMessage": "",
"spiderMessage": "",
"subscriptionMessage": "",
"unknownMessage": "",
"quotaSummaryMessage": "",
open: function () { },
update: function (userData) { },
updateHeight: function (heightData) { },
close: function () { },
onOpened: function () { },
onUpdated: function (userData) { },
onHeightUpdated: function (heightData) { },
onClosed: function () { }
},
"embeddedConfirmation": {
"element": "",
"zIndex": 0,
open: function (title, message) { },
close: function () { },
onOpened: function (title, message) { },
onClosed: function () { }
},
"modalFrame": {
open: function (url) { },
updateHeight: function (heightData) { },
close: function () { },
"zIndex": 0
},
"modalPaywall": {
open: function (url) { },
close: function () { }
},
"accessGranted": function (resourceAccessData) { },
"accessDenied": function (resourceAccessData) { },
"getOriginalURL": function () { },
"getAccessMessage": function (resourceAccessData) { },
"closeURL": ""
}
The following options can be specified as properties on the root of an options object:
PaywallSettings Object
Key Name | Description | Additional Notes |
---|---|---|
resourceKey | The external key used to identify this resource. | 50 Chars Max, If left blank, the current URL will be used. It will be the right-most 50 characters of the path. Characters not matching a-zA-z0-9 will be substituted with a dash character. |
resourceURL | The URL for this resource | By default, will be the current document URL. |
desktopPaywallType | The type of paywall to display at desktop resolutions | Value can be Modal , Redirect , or Embedded |
mobilePaywallType | The type of paywall to display at mobile resolutions | Value can be Modal , Redirect , or Embedded |
mobileMaxWidth | Resolutions with a width less than or equal to this value will be considered mobile. | Unit-less value is interprested as px . A value of 360 will therefore represent 360px |
embeddedAdBlockerDetection | “element” is where Ad Block Detection messaging appears | zIndex can be set in Property management, or be overridden |
embeddedPaywall | “element” is where Ad Block Detection messaging appears | zIndex can be set in Property management, or be overridden |
embeddedWallet | “element” is where Ad Block Detection messaging appears | zIndex can be set in Property management, or be overridden |
accessGranted ( ) | A callback function for when the user is granted access to the resource | See example below. |
accessDenied ( ) | A callback function for when the user is denied access to the resource | |
getOriginalURL ( ) | A function that returns the URL of the document being viewed. This is used when redirections occur to eventually redirect the user back to the original resource they were viewing | By default, document.URL is used |
getAccessMessage ( ) | A function that returns an access message based on the user’s access to the current resource. This message appears in the embedded wallet when the user clicks the lock icon | A ResourceAccessData Object will be passed in. Typically, you will switch based on ResourceAccessData.AccessReason. A full list of possible values is listed below. |
closeURL | The URL that the user will be redirected to if they close a paywall of type Modal or Redirect |
By default, the user will be sent to the previous page in their browser history |
Example Specifying a Resource Key
This will provide a resource key to be used instead of the current URL.
iMoneza.paywall.init('744935CD-D8D9-E311-B48B-BC305BD0D54E', {
resourceKey: 'My-Test-Page'
});
Example Using an accessGranted
Callback
The accessGranted
function is called when access to a page is granted via client-side access control. A single object is passed to the callback function containing data about the access request, including current quota data (if applicable), subscription data, and single purchase data. Basic user data is also passed along, as is the reason why access is granted.
This example displays whether or not the user is logged in. It then displays the reason why they have access to the page. If a quota is enforced, it displays how many quota hits the user has and how many they are allowed.
iMoneza.paywall.init('744935CD-D8D9-E311-B48B-BC305BD0D54E', {
accessGranted: function (resourceAccessData) {
$('#iMonezaUsername').text(resourceAccessData.IsAnonymousUser ? 'Not logged in' : 'Logged in as ' + resourceAccessData.UserName);
var text = '';
switch (resourceAccessData.AccessReason) {
case 'Quota':
text = 'You have viewed ' + resourceAccessData.Quota.HitCount + ' of your ' + resourceAccessData.Quota.AllowedHits + ' pages.';
break;
case 'Subscription':
text = 'Your subscription expires on ' + resourceAccessData.ExpirationDate + '.';
break;
case 'Purchase':
text = 'You purchased unlimited access to this page.';
break;
case 'Free':
text = 'This page is available for free.'
break;
case 'PropertyUser':
text = 'You are an admin, manager, or guest of this property.'
break;
}
$('#iMonezaAccess').text(text);
}
});
Example Using the accessDenied
Callback
The accessDenied
function is called when access to a page is denied. The same object is passed to this function as to the accessGranted
function.
This example displays the user’s user name (if they’re logged in) and tells them they do not have access to the page.
iMoneza.paywall.init('744935CD-D8D9-E311-B48B-BC305BD0D54E', {
accessDenied: function (resourceAccessData) {
$('#iMonezaUsername').text(resourceAccessData.IsAnonymousUser ? 'Not logged in' : 'Logged in as ' + resourceAccessData.UserName);
$('#iMonezaAccess').text('You do not have access to this page.');
}
});
Example Using the modalFrame.open
and modalFrame.close
Callbacks
These callbacks allows merchants to customize the modal IFRAME rendered around the paywall. Both callbacks must be used together.
iMoneza.paywall.init({'744935CD-D8D9-E311-B48B-BC305BD0D54E', {
modalFrame: {
open: function (url) {
var docWidth = window.innerWidth,
docHeight = window.innerHeight,
customWidth = 700,
customHeight = 600
body = document.querySelectorAll('body')[0];
body.insertAdjacentHTML('afterbegin',
'<div id="CustomOverlay" style="position: absolute; width: ' + customWidth + 'px; height: ' + customHeight + 'px; margin-top: ' + ((docHeight - customHeight) / 2) + 'px; margin-left: ' + ((docWidth - customHeight) / 2) + 'px; z-index: 10001"><a href=\"javascript:CustomCloseAndRedirect()\">Close</a><iframe src=\"' + url + '\" width="100%" height="100%" frameborder="1"></iframe></div>'
);
body.insertAdjacentHTML('afterbegin',
'<div id="CustomOverlayBackground" style="position: fixed; left: 0px; top: 0px; width:100%; height:100%; z-index: 10000; background-color: black;"></div>'
);
},
close: function () {
document.getElementById('CustomOverlay').parentNode.removeChild(document.getElementById('CustomOverlay'));
document.getElementById('CustomOverlayBackground').parentNode.removeChild(document.getElementById('CustomOverlayBackground'));
}
}
});
logOut
Method
The logOut
method will log out the current user. It will perform a redirect to iMoneza to log the user out on both iMoneza and the your site.
You can optionally pass a returnURL
parameter to specify the URL the user should be redirected to after they’ve been logged out. By default, they’ll be returned to the page from which they initiated the logout.
var logOut = function (returnURL) {
if (returnURL == null)
returnURL = window.top.location.href;
iMoneza.cookies.eraseCookie('iMonezaUT');
iMoneza.cookies.eraseCookie('iMonezaLT');
// Remove the iMonezaUT parameter from the URL, if it exists
returnURL = returnURL.replace('iMonezaUT=', 'iMonezaUTCancel=');
returnURL = returnURL.replace('iMonezaLT=', 'iMonezaLTCancel=');
window.location.replace(_uiBaseURL + 'Paywall/ExternalLogout?ReturnURL=' + encodeURIComponent(returnURL));
};
You have programatic access to the details of the selected Resource via the ResourceAccess object.
ResourceAccess Response Object
{
"UserToken": "635f9d47-3416-40bc-b9f0-cb65459852ae|635978154112661889|mGhURnAejYjKmw0UGVK5QRYCJbgIxFBn8CeCrC82Q",
"PropertyName": "Test Newspaper",
"ResourceName": "Home Page",
"UserName": "Anonymous User",
"FirstName": "",
"IsAnonymousUser": true,
"WalletBalance": 0.0,
"PictureURL": "",
"Quota": {
"IsEnabled": false,
"HitCount": -1,
"AllowedHits": -1,
"PeriodStartDate": "2016-05-02T19:50:11.2661889Z",
"PeriodName": "",
"IsMet": true
},
"Subscription": {
"IsExpired": false,
"ExpirationDate": "2016-05-02T19:50:11.2661889Z",
"IsCurrent": false,
"SubscriptionGroupID": ""
},
"Purchase": {
"IsPurchased": false
},
"AccessReason": "Free",
"AccessActionURL": "",
"AdBlockerStatus": "AdBlockerNotDetected",
"IsNoCost": true,
"IsAdSupported": false,
"AdSupportedMessageTitle": null,
"AdSupportedMessage": null
}
ResourceAccess Object
Key Name | Description | Additional Notes |
---|---|---|
UserToken | Not for developer consumption. | |
PropertyName | Name of Merchant Property | |
ResourceName | Name of Resource | |
UserName | Authenticated User’s User Name | Used as a means to log in with username/password |
FirstName | Authenticated User First Name | |
IsAnonymousUser | Value is true if not Authenticated |
|
WalletBalance | Authenticated User’s Account Balance | |
PictureURL | Authenticated User’s Logo | If signing up via social media |
Quota | Complex Object | See below |
Subscription | Complex Object | See below |
Purchase | Complex Object | See below |
AccessReason | Textual Access Reason | Can be Free or Purchase or Deny . See below for full list. |
AccessActionURL | ||
AdBlockerStatus | Status of client AdBlocker | Can be “AdBlockerNotDetected” or “AdBlockerDetected” and others |
IsNoCost | A value of true represents no payment will be required to access this Resource |
Pricing model could be free, price could be $0.00, or could be ad supported. |
IsAdSupported | If true , Access is Ad Supported |
|
AdSupportedMessageTitle | Defined by Merchant | |
AdSupportedMessage | Defined by Merchant |
All possible AccessReason values
Reason | Description |
---|---|
Deny | Access not granted |
Quota | Access granted, quota not reached |
Subscription | Access granted, valid subscription |
Purchase | Access granted due to the completion of a purchase |
Free | Access granted for free Resource |
PropertyUser | Access granted when a user is set as a Property Guest |
AdSupported | Access granted by removing Ad Blocker |
Quota Object
Key Name | Description | Additional Notes |
---|---|---|
IsEnabled | If true , metered access is enabled |
A Property-wide setting |
HitCount | Increments value for each Quota-enabled resource | A User-specific setting |
AllowedHits | Maximum number of free Resources under Quota per User | A User-specific setting |
PeriodStartDate | The beginning of the month for considering a Quota | |
PeriodName | ||
IsMet | Will be set to true when Quota is met |
Subscription Object
Key Name | Description | Additional Notes |
---|---|---|
IsExpired | If true , access to Resources in this group will not be granted |
|
ExpirationDate | End date of periodic subscription | |
IsCurrent | If true , it is a valid subscription |
|
SubscriptionGroupID | The unique identifier of a Subscription | GUID |
Successful Grant
userData Response Object
{
"UserToken": "",
"UserName": "",
"FirstName": "",
"IsAnonymousUser": false,
"WalletBalance": 0.0,
"PictureURL": ""
}
The following options can be specified as properties on the root of an options object:
Key Name | Description |
---|---|
UserToken | Not for developer consumption. |
UserName | Authenticated User’s User Name |
FirstName | Authenticated User First Name |
IsAnonymousUser | True if not Authenticated |
WalletBalance | Authenticated User’s Wallet Balance |
PictureURL | Authenticated User’s Logo |
sendHeight() HeightData
A MutationObserver watches the DOM of the embedded paywall. Upon height changes, the parent page may respond to changes in height. The sendHeight()
function can be called with new height values to regulate the dimensions of the iframe which hosts the embedded paywall.
{
"clientHeight": 0,
"scrollHeight": 0,
"offsetHeight": 0
}
Example
var updateEmbeddedWindowHeight = function (heightData) {
stopEmbeddedDialogMutationObserver();
if (!heightData)
heightData = _lastHeightData;
_lastHeightData = heightData;
if (heightData.offsetHeight > 0)
_embeddedWindowLowerCover.innerHTML = '';
var paywallHeight = heightData.offsetHeight;
var expanderHeight = parseInt(_embeddedWindowExpander.style.height.replace('px', ''));
var paywalledElementHeight = _embeddedWindowElement.offsetHeight - expanderHeight;
var lowerCoverTop = parseInt(_embeddedWindowFrameWrapper.style.paddingTop.replace('px', '')) + paywallHeight;
var lowerCoverHeight = paywalledElementHeight - lowerCoverTop;
var visibleHeight = 0;
var dialogHeight = document.getElementById('imoneza-embedded-paywall-dialog').clientHeight;
var coverBackgroundColor = iMoneza.utilities.hexToRGB(_options.embeddedPaywall.cover.backgroundColor);
if (lowerCoverTop > paywalledElementHeight) {
lowerCoverHeight = 0;
expanderHeight = lowerCoverTop - paywalledElementHeight;
}
if (_options.embeddedPaywall.cover.visibleHeightMode == "Percent")
visibleHeight = (paywalledElementHeight / 100 * _options.embeddedPaywall.cover.visibleHeight);
else
visibleHeight = _options.embeddedPaywall.cover.visibleHeight;
if (dialogHeight == 0) {
_embeddedWindowFrameWrapper.style.background = 'linear-gradient(to bottom, rgba(' + coverBackgroundColor.r + ',' + coverBackgroundColor.g + ',' + coverBackgroundColor.b + ',0) 0%,rgba(' + coverBackgroundColor.r + ',' + coverBackgroundColor.g + ',' + coverBackgroundColor.b + ',1) 100%)';
} else {
var pct = (visibleHeight / (visibleHeight + dialogHeight)) * 100;
_embeddedWindowFrameWrapper.style.background = 'linear-gradient(to bottom, rgba(' + coverBackgroundColor.r + ',' + coverBackgroundColor.g + ',' + coverBackgroundColor.b + ',0) 0%,rgba(' + coverBackgroundColor.r + ',' + coverBackgroundColor.g + ',' + coverBackgroundColor.b + ',1) ' + pct + '%)';
}
document.getElementById('imoneza-embedded-paywall').height = paywallHeight + 'px';
_embeddedWindowLowerCoverWrapper.style.top = lowerCoverTop + 'px';
_embeddedWindowLowerCover.style.height = lowerCoverHeight + 'px';
_embeddedWindowExpander.style.height = expanderHeight + 'px';
_embeddedWindowFrameWrapper.style.paddingTop = visibleHeight + 'px';
startEmbeddedDialogMutationObserver();
};
The following options can be specified as properties on the root of an options object:
Key Name | Description | Additional Notes |
---|---|---|
clientHeight | document.documentElement.clientHeight | |
scrollHeight | document.documentElement.scrollHeight | |
offsetHeight | document.documentElement.offsetHeight |
Examples
Custom Function Overrides
Once a user has been “Granted access” to a Resource, you may customize the user experience by making use of the embeddedConfirmation.open(title, message)
function.
<head>
<title>Our Website</title>
<script src="https://cdn.imoneza.com/paywall.min.js"></script>
<script type="text/javascript">
iMoneza.paywall.init('b865156f-9e0d-48b6-a2a0-097456f689ec', {
embeddedConfirmation: {
open(title, message) {
alert(message);
}
}
});
</script>
</head>
When ad blocker detection is set to Show Warning
, you may customize the user experience by making use of the embeddedAdBlockerDetection.openWarning(title, message)
function.
<div id="customAdBlockerWarning" style="display: none;">
<h3 id="customAdBlockerWarningTitle"></h3>
<p id="customAdBlockerWarningMessage"></p>
<div onclick="$('#customAdBlockerWarning').hide();">Close</div>
</div>
<script type="text/javascript">
iMoneza.paywall.init('b865156f-9e0d-48b6-a2a0-097456f689ec', {
embeddedPaywall: {
element: '#content'
},
embeddedAdBlockerDetection: {
openWarning: function (title, message) {
$('#customAdBlockerWarningTitle').text(title);
$('#customAdBlockerWarningMessage').text(message);
$('#customAdBlockerWarning').show();
}
}
});
</script>
When ad blocker detection is set to Require Disable
, you may customize the user experience by making use of the embeddedAdBlockerDetection.openDialog(title, message)
function.
<div id="customAdBlockerWarning" style="display: none;">
<h3 id="customAdBlockerWarningTitle"></h3>
<p id="customAdBlockerWarningMessage"></p>
<div onclick="$('#customAdBlockerWarning').hide();">Close</div>
</div>
<script type="text/javascript">
iMoneza.paywall.init('b865156f-9e0d-48b6-a2a0-097456f689ec', {
embeddedPaywall: {
embeddedAdBlockerDetection: {
openDialog: function (title, message) {
alert(message);
}
}
});
</script>
Setting resourceKey based on URL parameter or unique ID
The resourceKey identifies the resource to iMoneza. A resource key may be part of the URL parameters, such as www.mydomain.com/?id=1234321
. In this case, override the resourceKey based on the URL parameter.
<html>
<head>
<title>Our Website</title>
<script src="https://cdn.imoneza.com/paywall.min.js"></script>
<script type="text/javascript">
iMoneza.paywall.init('b865156f-9e0d-48b6-a2a0-097456f689ec',
{
resourceKey: "id=1234321"
});
</script>
</head>
<body>
...
</body>
</html>
A resource key may also be found in the DOM. In this case, override resourceKey based on element ID (or path).
<html>
<head>
<title>Our Website</title>
<script src="https://cdn.imoneza.com/paywall.min.js"></script>
<script type="text/javascript">
iMoneza.paywall.init('b865156f-9e0d-48b6-a2a0-097456f689ec',
{
resourceKey: "content"
});
</script>
</head>
<body>
<div id="header">
...
</div>
<div id="content">
...
</div>
</body>
</html>
Loading page content via AJAX in onAccessGranted
<script type="text/javascript">
iMoneza.paywall.init('b865156f-9e0d-48b6-a2a0-097456f689ec', {
accessGranted: function (data) {
// Supply your own service to load the full content upon accessGranted:
$('#content').load("/GetPageContent.ashx?FilePath=" + encodeURIComponent(window.location.pathname) + "&ResourceKey=" + iMoneza.paywall.getResourceKey() + "&ResourceURL=" + encodeURIComponent(window.location.href));
}
});
</script>
Resizing a custom modal implementation
<div id="customAdBlockerWarning" style="display: none;">
<h3 id="customAdBlockerWarningTitle"></h3>
<p id="customAdBlockerWarningMessage"></p>
<div onclick="$('#customAdBlockerWarning').hide();">Close</div>
</div>
<script type="text/javascript">
iMoneza.paywall.init({'744935CD-D8D9-E311-B48B-BC305BD0D54E', {
modalFrame: {
updateModalFrameHeight: function (heightData) {
if (!document.getElementById('imoneza-modal-overlay'))
return;
// Note:
// clientHeight: document.documentElement.clientHeight,
// scrollHeight: document.documentElement.scrollHeight,
// offsetHeight: document.documentElement.offsetHeight
if (heightData.scrollHeight != heightData.offsetHeight || heightData.scrollHeight != heightData.clientHeight) {
var newHeight = heightData.offsetHeight;
document.getElementById('imoneza-modal-overlay').style.height = newHeight + 'px';
document.getElementById('imoneza-modal-overlay-iframe').scrolling = 'no';
}
}
}
});
</script>
Providing custom text in getAccessMessage
Embedded Wallet “Purchase Message”
<script src="https://cdn.imoneza.com/paywall.min.js"></script>
<script type="text/javascript">
iMoneza.paywall.init('b865156f-9e0d-48b6-a2a0-097456f689ec',
{
getAccessMessage: function (resourceAccessData)
{
if (resourceAccessData.AccessReason === "Subscription")
{
// override message with exp.date
}
var subscriptionMessage
}
});
</script>
Pagination Ignorance
Some resources may span multiple “pages” but realistically are associated with a single resource. To ignore differences in query string parameters, as with the below example, supply the base path with which to identify the resource. Below represents a Resource spanning 3 pages:
www.mydomain.com/news/long-article?page=1
www.mydomain.com/news/long-article?page=2
www.mydomain.com/news/long-article?page=3
Ignoring pagination for this Resource:
<html>
<head>
<title>Our Website</title>
<script src="https://cdn.imoneza.com/paywall.min.js"></script>
<script type="text/javascript">
iMoneza.paywall.init('b865156f-9e0d-48b6-a2a0-097456f689ec',
{
resourceKey: "/news/long-article"
});
</script>
</head>
<body>
...
</body>
</html>