Paywall
Iteras has a simple Javascript API available for implementing a paywall on your own site.
Under the hood, the API works the way that visitors are denied access unless they have a pass cookie called "iteraspass" authorizing them. This cookie is set in the user's browser on your domain, either through an ordering flow or by the paywall login iframe upon successful login. It is usually valid for an extended period of time.
This design minimizes the coupling between your system and Iteras. Visitors do not depend on access to an Iteras server to view content besides the initial login, improving fault tolerance and response time.
The pass cookie must be regenerated from time to time by Iteras.
If the regeneration succeeds, the user can keep on accessing the
content, if it fails because the user no longer has access, the
cookie is deleted so the user is denied access. The cookie
regeneration is done automatically by the
Iteras.wall function that you use to check for
access, and by Iteras.refreshPass on pages that are
not paywalled, see keeping
visitors logged in.
To get started, you need to add a paywall inside Iteras and configure its settings there. This gives you a paywall id for use in the API.
There are a couple of things you then need to prepare. When visitors are not logged in to the paywall, they need to see an explanation that paywall access is required, a strong call to action for people who have not signed up yet, e.g. with a link to the the ordering iframe, and then some means of logging in. That could either the paywall login iframe or a link to a page with it.
Basic paywall setup with redirects
The most basic paywall setup is using redirects to guide visitors through the flow.
To do this, you need to setup a landing page for people who are not logged in. As mentioned above, you’d usually include an explanation that paywall access is required, a strong call to action for people who have not signed up yet and some means of logging in for those who have already signed up.
Say the path to your landing page is "/paywall/landing.html", then you call
Iteras.wall({ paywallid: "XXXXXX", redirect: "/paywall/landing.html" })
on all pages you want paywalled. This call checks that a cookie
with the right paywall id exists, if not it redirects to the URL
given by redirect.
-
paywallid string or arrayThe paywall ID, e.g.
XXXXXX. It’s shown in the paywall settings inside Iteras. Pass a list of paywall IDs to check for a pass to either of them.Log in, or send your API key as a bearer token, to see the paywalls set up for your account.
-
redirect stringThe URL to redirect to when the visitor has no valid pass. Omit both
redirectandunauthorizedto do nothing for unauthorized visitors (the pass cookie is still checked and regenerated or deleted). -
unauthorized functionA callback invoked instead of a redirect when the visitor has no valid pass, e.g. to block off only part of the page. The function may be called immediately or later, after the pass cookie is regenerated.
-
access string Defaults to
"sub"The minimum access level required to pass the wall. See the access levels section.
In case you need to check for a pass to either of a number of paywall ids, put in a list, like this
Iteras.wall({ paywallid: ["XXXXXX", "YYYYYYY"], redirect: "/paywall/landing.html" })
The call to Iteras.wall will also automatically
regenerate the cookie from time to time by contacting the Iteras
server, or delete it if the user no longer has access.
The landing page may get some query/GET parameters starting with "iteras", e.g.
http://www.example.com/paywall/landing.html?iterasnext=...&iterasaccess=...
These are read by the paywall login and ordering iframes, so if you don’t have the iframes embedded directly in the landing page but instead accessible through links, you should append all query parameters starting with "iteras" to those links. Otherwise, visitors will have reduced functionality, e.g. people will not be redirected back to the original page upon logging in.
Paywall setup with inline handling
In case you need something else than a redirect upon
un-authorized access, e.g. in you want to only block of part of
the page, you can provide an "unauthorized" callback to the
Iteras.wall function instead of the "redirect"
parameter, like this
function myPaywallHandler() { ... }
Iteras.wall({ paywallid: "XXXXXX", unauthorized: myPaywallHandler })
In your callback function, as mentioned above you then need to explain to the visitor that paywall access is required, provide a strong call to action for people who have not signed up yet and some means of logging in for those who have already signed up, for instance by inserting a box with this information.
Note that the Iteras.wall function may call the
handler or return immediately and call the handler later. The
latter may happen in case the iteraspass
cookie is regenerated (which may take some milliseconds) and it
turns out the visitor no longer has access.
This can be inconvenient if you have already checked that the user was logged in. Sometimes the easiest way out is simply a redirect, forcing a page rerender.
If you omit both "redirect" and "unauthorized",
nothing will happen in case of an unauthorized visitor, but the
code will still check the pass cookie from time to time and delete
it if it is no longer valid.
You might also need to determine if the user is signed in:
Iteras.signedIn() // returns true or false
Or access information contained in the paywall pass cookie:
Iteras.paywallPass()
// returns
{
"paywalls": {
"XXXXXX": "sub",
"YYYYYY": "user"
},
"expires": Date("2026-10-31T21:36:50Z"),
"customer": "123456",
"ipaddress": "93.176.69.74"
}
Logging out of the paywall
To log out from the paywall, call
Iteras.logoutFromWall()
e.g.
<button id="logout">Log out</button>
<script>
document.getElementById("logout").onclick = function () {
Iteras.logoutFromWall();
};
</script>
Upon completing the log out, by default the page will be reloaded. You can redirect to another page by specifying a redirect option, like this
Iteras.logoutFromWall({ redirect: "/some/url" })
You can also specify redirect: null to prevent the reload.
Access levels
There are currently two access levels in Iteras.
- Visitors with active subscriptions (on campaigns with digital access) are at the "sub" level.
- Visitors registered as subscribers but with no active subscriptions are at the "user" level.
It is sometimes useful to give the user-level visitors access to selected areas so you can configure Iteras to hand out paywall passes to them, and then add the "access" parameter to the wall function, like this
Iteras.wall({ paywallid: "XXXXXX", redirect: "/paywall/landing.html", access: "user" })
for user-accessible pages and
Iteras.wall({ paywallid: "XXXXXX", redirect: "/paywall/landing.html", access: "sub" })
for pages for the actual subscribing subscribers.
IP-based access control
Iteras internally has support for adding an IP access field to subscriptions.
It has the effect that when the paywall login iframe is shown, a request is sent to the server and if the request IP address matches a subscription, the client is automatically logged in as the corresponding subscriber as if the client had submitted the password form. From then on, everything else works as usual.
Note that IP-based access can be more difficult to control as it depends on specific firewall and network settings in the client end, compared to the standard paywall which simply depends on a working browser. Often clients are not well-equipped to analyze network problems - they just want access ASAP.
We have a helpdesk article on diagnosing IP-related problems, but otherwise we cannot really help.
Paywall pass cookie
The paywall pass cookie consists of a number of fields separated by | with a signature at the end beginning with /, e.g.
sub|n8fsoupukhv3|2016-01-23T12:35:29Z|31168|123.123.123.123/sha256:596c625c185499e6a4394dbcec8713347ba7d0e67acb1fe3fe876f424f35bfc7
The fields can’t contain | or other characters not allowed in cookies so a simple string split can be used for parsing. The fields are currently:
- access level - in case of multiple paywall ids, the level for each paywall is separated with a comma in the same order as the paywall ids in the next field
- paywall id - in case of multiple paywall ids, they are separated with a comma, e.g.
XXXXX,YYYYY - UTC timestamp for when the pass expires (normally requiring new login)
- customer number
- IP address of other end when pass was granted
You can count on the ordering of the fields, but we might add more fields at the end in the future so don’t write code that assumes that the number of fields is fixed.
The signature is everything to the right of the last / in the pass and consists of a signing algorithm identifier followed by : followed by the actual signature. The signing algorithm is run on everything to the left of the /.
"sha256" means HMAC SHA256 with hexadecimal numbers as output (this is a standard algorithm with implementations in many programming environments). The key used for the HMAC is the signing key you can find in the settings inside Iteras.
The signature is not checked in the JS API, but you can check it server-side to ensure that the cookie was actually generated by Iteras.
In case the pass cookie is needed on subdomains, the cookie domain can can be set for the plugin. Remember to configure it before using the Iteras paywall API.
<script src="https://app.iteras.dk/static/api/iteras.js"></script>
<script>Iteras.cookieDomain = ".example.com";</script>
Server-side check
Note that the Javascript paywall API here as a client-side solution allows sufficiently skilled people to trick the paywall.
If this is a problem, make a server-side check of the pass cookie as described in the previous section and modify the server to prevent content from being sent to people without a valid cookie.
However, as long as it is difficult enough to circumvent the paywall for 99.999% of your target audience - especially on relatively locked-down consumer tablets and phones - it may not be cost-effective to take this extra step.
Keeping visitors logged in
Iteras.wall only renews the pass cookie on the pages
where you call it. To keep visitors who mostly read content that
is not paywalled logged in, call this on every page:
Iteras.refreshPass()
It does nothing for visitors who are not logged in, and only contacts Iteras once in a while.
Safari deletes cookies written by Javascript after 7 days without
a visit to your site, and sometimes sooner. A cookie set by your own
server with a Set-Cookie header is not affected. To
have your server set the pass cookie, point
Iteras.passEndpoint at a URL on your site before
loading the API:
<script>
window.Iteras = window.Iteras || {};
window.Iteras.passEndpoint = "/iteras-pass";
</script>
<script src="https://app.iteras.dk/static/api/iteras.js"></script>
The API still writes the cookie itself, and also posts the pass to the endpoint whenever it sets, renews or deletes it. If the endpoint fails, the visitor stays logged in with the cookie the API wrote.
The endpoint receives a form-encoded POST with these
fields:
-
passaction string required
setorclear. -
pass stringThe pass, for
set. -
maxage integerSeconds the cookie should live, for
set. -
redirect stringSent when the visitor has just logged in. The request is then an ordinary form submission, and you reply with a redirect to this URL.
For set, check the signature and expiry of the pass as
described in paywall pass cookie,
and if they check out reply with
Set-Cookie: iteraspass=<pass>; Path=/; Expires=<expiry>; Secure; SameSite=Lax
using the expiry in the pass, or maxage if that is
sooner. Write the pass as it is without URL-encoding it. Note that
a pass for several paywalls contains commas, which some cookie
libraries refuse. Don't make the cookie HttpOnly, the
API needs to read it. If you set
Iteras.cookieDomain, set the same domain on the
cookie. For clear, expire the cookie.
When redirect is present, check that it points at
your own site and redirect to it, also if you rejected the pass. To
prevent other sites from posting to the endpoint, reject requests
with an Origin header naming another site, but accept
a missing header or Origin: null.