# Paywall providers
We have created a system to allow developers to implement paywall providers into Marfeel in an easy way. The way this system works is similar to the current ad server or analytics providers.
# How to create a paywall provider
WARNING
- The new Paywall providers are not compatible with legacy tenants (non-XPlib).
# Preliminary steps
- Make sure the Paywall Provider hasn't been created yet by looking in the Paywall providers repository (opens new window).
# Scaffolding
In order to create a new paywall provider, we need to create a folder inside the packages folder with the name of the new provider. This one needs to have the following structure. You can always copy a folder from an already existing provider and afterward make all the necessary changes.
packages/newProviderFolder
├─── schema
│ │ index.json
│ ├─── test
│ └──── valid
│ │ index.test.json
│ └──── wrong
│ │ index.test.json
├─── src
│ │ index.js
│ │ index.test.js
└── package.json
└── package-lock.json
└── .eslintignore
# Implementation
When implementing a paywall provider, only the logic needs to be implemented, most of the UI is already implemented in Marfeel. So, in order to properly organize each providers logic, follow this structure:
export default class NewProvider {
constructor(json, marfeelEnvironment) {
// set the parameters given in the config of the paywall.json
}
static buildFromJson(json, marfeelEnvironment) {
return new NewProvider(json, marfeel);
}
login() {
return Promise.resolve();
}
isUserLoggedIn() {
return Promise.resolve();
}
logout() {
return Promise.resolve();
}
onNavigationChange() {
//do something
}
getActionItems() {
return Promise.resolve([]);
}
}
In the constructor we receive 2 arguments:
json object
: is the configuration set in thepaywall.json
file in the tenant's repositorymarfeelEnvironment
contains several utilities that can be used to install scripts and retrieve context information from Marfeel. They are injected into the provider to avoid exposing Marfeel source code and to keep the provider's implementation decoupled from Marfeel core. It contains ahideAds
function that can be called withNONE
,CLIENT
,ALL
,TYPE
orPERCENTAGE
, based on the ads that we want to hide. Find below some use cases:
//Ads running normally
marfeelEnvironment.paywall.hideAds('NONE')
//All ads disabled
marfeelEnvironment.paywall.hideAds('ALL')
//Client ads disabled, only Marfeel ads are showing
marfeelEnvironment.paywall.hideAds('CLIENT')
//Marfeel ads disabled, only client ads are showing
marfeelEnvironment.paywall.hideAds('MARFEEL')
//Taboola and Teads ads type are disabled (ad type as you find in inventory.json)
marfeelEnvironment.paywall.hideAds('TYPE', ['taboola', 'teads'])
//75% of the ads (client and Marfeel) are disabled. null value is required for second parameter as the percentage is not affected by ad types.
marfeelEnvironment.paywall.hideAds('PERCENTAGE', null, 0.75)
The methods login
, isUserLoggedIn
, logout
, onNavigationChange
and getActionItems
are mandatory. If any of them are missing, acid tests fail.
# Paywall action menu
In order to have the paywall actions like login, logout, subscribe, etc. closer to the user we have created a separate menu that is placed on the top right corner of the header. This menu is already implemented within Marfeel through a class called PaywallActionsBuilder (opens new window) in MarfeelXP. The only thing this class needs to know is which items should the menu have.
Define those items inside the getActionItems
method as an array of json objects.
An item can have different properties:
text
: the name of the button. [string]link
: if it needs to redirect the user to a specific link. [string]class
: a css class for the button. [string]id
: an id for the button. [string]action
: a function to be executed when clicking the item/button. [function]cta
: if you want it to be a Call To Action item. Those appear in the top of the sections when the user is not logged in (maximum amount: 2). [boolean, default false]
Take into consideration that you should also distinguish the items returned based on if the user is logged in or not. Here's an example of how it could look like:
if (this.isUserLoggedIn) {
return [
{
text: 'My account',
link: 'www.example.com/myaccount'
},
{
text: 'Logout',
action: this.logout,
class: 'logoutClass'
}
];
} else {
return [
{
text: 'Subscribe',
class: 'subscribeClass',
cta: true
},
{
text: 'Login',
action: this.login,
class: 'loginClass',
cta: true
}
];
}
Example of the CTA buttons:
Example of the action menu:
# Unit tests
A Paywall Provider must contain unit tests to be deployed. Providers' unit tests must be written using JEST (opens new window).
The test for the provider's implementation entry point is mandatory and can be found at src/index.test.ts
, but you can create as many test files as necessary:
src/helpers.test.ts
src/utils.test.ts
- ...
Run the test suite by executing the following command from the provider's root folder:
npm run test
If you want to debug, you can use:
npm run test:debug
To check if your provider passes the acid-tests execute:
npm run acid-tests
# JSON Schema
In addition to its implementation and unit tests, every provider must contain a JSON schema (opens new window)
The schema must be at schema/index.json
and describes which properties and values can be used to configure the paywall provider in paywall.json
files.
Validate the provider's schema with at least one valid and one wrong test:
schema/tests/valid/index.test.json
{
"type": "newProviderName",
"config":{
"xxx": "xxx",
...
},
"options": {}
}
schema/tests/wrong/index.test.json
{
"type": "newProviderName",
"config":{
"xxx": "xxx",
...
}
}
Each folder, valid
and wrong
, can contain as many *.test.json
files as necessary.
# Deployment
- If the Paywall Provider has already been deployed before, make sure you've increased its version in the
package.json
file, following the SemVer spec (opens new window). Otherwise, the build fails, blocking deployment. - Open a Pull Request and merge your commit to the master branch.
- The build process will start immediately after the merge. You can follow the deployment status at the Actions tab of the Paywall Provider repository.
- If everything goes well, the Paywall Provider package will be published in the Marfeel releases repository (opens new window) within 4 minutes approx.
TIP
If the build is broken, review the logs from GitHub and fix all the failures before trying again.