JavaScript SDK

Quickstart

Note: For those using WordPress, the Pigeon WordPress plugin in JS mode sets up the implementation for you.

The following example will initialize the Pigeon SDK on your site. Replace YOUR_PIGEON_SUBDOMAIN everywhere on this page with the Pigeon subdomain identified during setup (for example, my.yoursite.com), and load pigeon.js from that same subdomain so you always get the current SDK.

The SDK has no dependencies. It does not require jQuery.

<script type="text/javascript" src="//YOUR_PIGEON_SUBDOMAIN/c/assets/pigeon.js"></script>
<script type="text/javascript">

var Pigeon = new PigeonClass({
	subdomain:'YOUR_PIGEON_SUBDOMAIN',
	fingerprint:true
});

Pigeon.paywall({
	// redirect: true || 'modal' Setting true or false tells Pigeon whether to redirect to
	// preset promotional page or not. Setting 'modal' tells the page to popup the
	// standard promotional dialog.
	redirect:'modal',
	free:false, // default: false. Setting true overrides the Pigeon Cloud presets, allowing this page to be free.
	success:function(response){
		// do stuff here with response
		// See the Response Reference in documentation for available variables.
	}
});
</script>

To check which SDK version a page is running, type PigeonClass.version in the browser console.

Content Wrappers

Use one of the following scenarios in your HTML/templates to protect your content when a visitor does not have access.

Scenario 1 - Remove all content

This wrapper will remove all the content within the wrapper.

<div class="pigeon-remove">
	<p>All content with a class of pigeon-remove will be removed if the visitor is not authorized.</p>
</div>

Scenario 2 - Remove one or more paragraphs

This wrapper keeps the first X paragraphs and removes the rest of the wrapped content. If the wrapper contains an <h1>, the first one is kept too. Anything else in the wrapper, such as images or embeds, is removed.

Example: One paragraph kept

<div class="pigeon-remove" data-pn="1">
	<p>The content of your article. Only this paragraph will show if the visitor is not authorized.</p>
	<p>This paragraph and any subsequent content will be removed if the visitor is not authorized.</p>
</div>

Example: More than one paragraph kept

<div class="pigeon-remove" data-pn="3">
	<p>Keep</p>
	<p>Keep</p>
	<p>Keep</p>
	<p>This paragraph and any subsequent content will be removed if the visitor is not authorized.</p>
</div>

Scenario 3 - Keep only the first paragraph

A shorthand for keeping exactly one paragraph. Everything in the wrapper except its first paragraph is removed.

<div class="pigeon-first-p">
	<p>This paragraph stays.</p>
	<p>This paragraph and everything after it is removed if the visitor is not authorized.</p>
</div>

Blurred Teaser

Content with a class of pigeon-blur is blurred and made unselectable when the visitor does not have access. Clicking it opens the subscribe dialog.

<div class="pigeon-blur">
	<p>This text is blurred for visitors without access.</p>
</div>

Note: Blurred content is still in the page source. Use pigeon-remove for anything that must not reach unauthorized visitors.

Promotional Wrapper

The following wrapper will show when a person does not have access. You can put your promotional copy and calls to action in there.

<div class="pigeon-context-promotion" style="display:none;">
	<!-- This is where you can promote your content. -->
	<!-- The link with a class of pigeon-open will open the pigeon modal -->
	<p>This page is available to subscribers. <a href="#" class="pigeon-open">Click here to sign in or get access</a>.</p>
</div>

These link classes work inside the promotional wrapper:

pigeon-open Opens the Pigeon dialog on its default view.
pigeon-open-plans Opens the Pigeon dialog on the paid plan options.
pigeon-open-login Opens the Pigeon dialog on the sign-in form.

To open the dialog from a link anywhere else on the page, call the widget methods described below, e.g. Pigeon.widget.openLoginDialog().

Access-Based Messages

Elements with a class of pigeon-message and a data-access attribute are shown or removed based on whether the visitor has access. Hide them by default so neither version flashes on load.

<!-- Shown to visitors with access, removed for everyone else -->
<div class="pigeon-message" data-access="enabled" style="display:none;">Thanks for subscribing!</div>

<!-- Shown to visitors without access, removed for everyone else -->
<div class="pigeon-message" data-access="disabled" style="display:none;">Subscribe to read the full story.</div>

Init

var Pigeon = new PigeonClass({
	subdomain:'YOUR_PIGEON_SUBDOMAIN'
});

Settings

subdomain type: string
required
The Pigeon subdomain identified during setup.
fingerprint type: bool
default: false
True turns on browser fingerprint to reduce cookie removal fraud in soft paywall scenarios.
widgetStatusSettings type: object
default: {}
Site-wide settings for widget.status(), in the same format as its own settings (e.g. {customCopy:{page:['article','articles']}}). Settings passed to widget.status() directly take precedence. Useful when a CMS plugin calls widget.status() for you.
serverGate type: bool
default: false
For publishers who also verify access on their own web server before serving premium pages. When true, the SDK stores the signed access token Pigeon issues in a cookie your server can verify. Contact support to set up the server side.
serverGateCookie type: string
default: 'pigeon_access'
The cookie name the server gate token is written to.
serverGatePromo type: bool
default: false
Set true only on the page your server gate shows to visitors without access. Once a reader gains access there, the page reloads so the gate serves the real content.
debug type: bool
default: false
Logs extra diagnostics to the browser console.
idp (DEPRECATED) type: bool
default: false
NOTE: This parameter is no longer needed. The SDK determines the proper IDP path internally now.
Set to true when pointing to a Pigeon subdomain that is not in the same context of the primary calling domain.

Paywall

Pigeon.paywall();

You can further customize the paywall settings with the settings below.

Settings

free type: bool | integer
default: false
Setting true overrides the Pigeon Cloud presets, thus allowing this page to be free. When using integer 0 == false, 1 == true, and 2 == restricted. Use the value 2 to make sure a page is restricted in a metered paywall scenario. In other words, that page cannot be metered, it requires enabled or paid access to view.
redirect type: bool | string
default: true
Setting true or false tells Pigeon whether to redirect to preset promotional page or not. Setting 'modal' tells the page to popup the standard promotional dialog.

success type: function( response )
The response function that is called after the authentication check has completed. See the Response Reference for available variables. You can use Pigeon.paywallPromise (promise as seen below) to run code on the callback response elsewhere in your code.
ignoreBodyHide type: bool
default:
false
True doesn't hide the body onload while paywall decides what to do.
blockPrivateMode type: bool
default:
true
Visitors browsing in a private/incognito window cannot use up a meter: on a paywalled page they see the Pigeon dialog instead of the content. Set false to let private-mode visitors meter normally.
contentId type: Integer | string
default: 0
Used in on-demand scenario. The unique id you use for the page or particular product.
contentTitle type: string
default: ''
Content title used for identifying content in a nice way.
contentDate type: string e.g. "YYYY-MM-DD HH:ii:ss"
default: ''
Content date used for time based access scenarios. Calculations are done based on the timezone set in your account from Settings > Environment.
contentPrice type: integer | float
default: 0
Used for the content price on-demand
contentValue type: integer
default: 0
Used for the content value meter. Used in the credit or voucher-based scenario.
contentPrompt type: bool
default: false
If true then prompt before taking credit on content value meter.
contentAccessStart type: string e.g. "YYYY-MM-DD HH:ii:ss"
default: none
On-demand and credit scenarios: when access to this content begins for buyers.
contentAccessEnd type: string e.g. "YYYY-MM-DD HH:ii:ss"
default: none
On-demand and credit scenarios: when access to this content ends for buyers.
contentPurchaseEnd type: string e.g. "YYYY-MM-DD HH:ii:ss"
default: none
On-demand and credit scenarios: after this date the content can no longer be purchased.
contentCategories type: array
default: null
The category IDs set for your content. These are matched against the paywall rules set from the Paywall Rule Editor. Example: [1234,1235,1236]
contentTags type: array
default:
null
The tag IDs set for your content. These are matched against the paywall rules set from the Paywall Rule Editor. Example: [1234,1235,1236]

Callbacks

You can use promises to do stuff with the callback response. Refer to the Response Reference section to see what variables you can use.

Note: Each call to Pigeon.paywall() creates a new Pigeon.paywallPromise. Attach your handlers after Pigeon.paywall() has been called. A promise saved before that call never resolves.

Pigeon.paywall({ redirect:'modal' });

Pigeon.paywallPromise.done(function(response){
	if( response.is_logged_in ){
		// User is logged in
	}

	if( response.allowed ){
		// User has access to the content
	}else{
		// Pigeon.widget.openSubscribeDialog();
	}
});

// If your page loads jQuery, $.when works too
$.when( Pigeon.paywallPromise ).then(function(response){
	// ...
});

Two special responses are worth handling:

  • disabled: 1 means Pigeon could not be reached (for example, a timeout). The SDK fails open: the content is shown, allowed is 1, and the widgets do not render.
  • special_access: 1 means the visitor was let through without a paywall check, such as an allowed search engine crawler or a whitelisted IP.

Widget

Pigeon Widgets allow you to control user status and sales funnel display. Call Pigeon.paywall() before any widget method.

widget.status()

This sets up an HTML unordered list that shows the user status. There are two formats, Standard and Sticky. Simply add the following HTML block as the placeholder for the widget. Style to match your site.

Standard Layout

<nav class="pigeon-widget-status"></nav>

See a styled example here (see it in action at PigeonDaily).

The HTML rendered in the above example. You can style to match your site's design.

<nav class="pigeon-widget-status">
	<ul>
		<li class="credits" style="display:none;"><a href="//YOUR_PIGEON_SUBDOMAIN/user/"></a></li>
		<li class="meter" style="">0 out of 3 pages left</li>
		<li class="group-ip-access" style="display:none;"></li>
		<li class="account" style="display:none;"><a href="//YOUR_PIGEON_SUBDOMAIN/user/">My Account</a></li>
		<li class="login" style=""><a href="//YOUR_PIGEON_SUBDOMAIN">Sign In</a></li>
		<li class="subscribe" style=""><a href="//YOUR_PIGEON_SUBDOMAIN">Subscribe</a></li>
		<li class="logout" style="display:none;"><a href="//YOUR_PIGEON_SUBDOMAIN/action/public/vo/logout">Sign Out</a></li>
	</ul>
</nav>

Sign In and Subscribe open the Pigeon dialog instead of following the link (Subscribe follows the link when your account uses a custom promotion page). When a visitor has access through a group's IP range, the Sign In item also gets a class of group-ip-login so you can style it differently.

This layout allows you to customize status widget to match the look of your site. This example style will get you started.

<style type="text/css">
	.pigeon-widget-status { float: right; margin: 2px 33px 0px 15px; }
	.pigeon-widget-status ul { margin: 0; padding: 0; }
	.pigeon-widget-status ul li { float: left; list-style: none; }
	.pigeon-widget-status ul li a { color: #666; border-left: 1px solid #dcdcdc; padding-left: 10px; margin-left: 13px; }
	.pigeon-widget-status ul li a:hover { color: #517ABA; }
	.pigeon-widget-status ul li:first-child a { border: none; padding: 0; margin: 0; }

	@media only screen and (max-width: 720px) {
	   .pigeon-widget-status {
		  float: none; width: 100%; margin: 0; padding: 10px 20px 20px 20px; overflow: hidden; box-sizing: border-box;
	   }
	}
</style>

Sticky Layout

This will stick at the top of the browser and go away when scrolling down, then show back when scrolling back up. When logged in the bar only shows user status when at the top or bottom of the browser.

<nav class="pigeon-widget-status pigeon-widget-status-sticky">
	<div class="pigeon-widget-status-wrap wrap"></div>
</nav>

This is example style for the Sticky Layout:

<style type="text/css">
	.pigeon-widget-status { position:fixed; height: 42px; padding: 10px; width: 100%; background: #000; z-index: 999997; font-size: 14px; text-align: center; }
	.pigeon-widget-status ul { display: inline-block; margin: 0 auto; padding: 0; float: right; }
	.pigeon-widget-status ul li { float: left; list-style: none; color: #CDCDCD; }
	.pigeon-widget-status ul li a {color: #cdcdcd; border-left: 1px solid #585858; padding-left: 10px; margin-left: 13px; }
	.pigeon-widget-status ul li a:hover { color: #517ABA; }
	.pigeon-widget-status ul li:first-child a { border: none; padding: 0; margin: 0; }

	@media only screen and (max-width: 600px) {
	   .pigeon-widget-status ul { float: none; }
	}
</style>

How to Initialize the Status Widget

You can initialize the status widget like this. The WordPress plugin in JS Mode initializes this automatically for you.

Pigeon.widget.status();

The customCopy parameter allows you to customize the copy of the status widget elements. The following are the defaults. Copy and paste the customCopy parameters you want to change.

Pigeon.widget.status({
	customCopy:{
		page:['page','pages'],
		meter: '%%available%% %%page%% left',
		restricted: 'Premium %%page%%',
		login: 'Sign In',
		logout: 'Sign Out',
		account: 'My Account',
		subscribe: 'Subscribe',
		groupIpAccess: 'Access provided by %%profile_parent_name%%',
		groupIpAccessGeneric: 'Access provided by your organization',
		groupIpLogin: 'Sign In',
		credits: 'Credits Left %%credit_total%%',
		getAccess: 'Get unlimited access'
	}
});

Settings

customCopy type: object
Overrides any of the copy defaults above. Only the keys you pass change.
groupNameMaxLength type: integer
default: 25
Group names longer than this show the groupIpAccessGeneric copy instead, with the full name in the tooltip. Set groupIpAccessGeneric to '' to always show the group name.
landingPage type: string
default: the landing page set on the paywall ruleset
The Pigeon page path Subscribe and Sign In open in the dialog.

Copy Variables

  • meter: %%available%%, %%limit%%, %%page%%
  • restricted: %%page%%
  • groupIpAccess: %%profile_parent_name%%
  • credits: %%credit_total%%

Set groupIpLogin to '' to hide the Sign In link for visitors on group IP access. Set getAccess to '' to keep showing the meter text when no pages are left.

If the status widget has already been initialized with the default settings, you can call the status method again and pass in your customCopy changes. This is often the case when using a CMS plugin such as WordPress—for example, the plugin automatically runs Pigeon.widget.status();

To apply your customizations, simply call the method again after the plugin runs, passing in the updated parameters. For instance, if you want to change the word “page” to “article,” you can do something like this:

Pigeon.widget.status(); // Run before by a CMS plugin for example with 'page' and 'pages' as the default copy.

Pigeon.widget.status({
	customCopy:{
		page:['article','articles'] // Any place the 'page' variable is used now uses 'article' or articles in its place.
	}
});

Alternatively, pass the same settings once as widgetStatusSettings when you create PigeonClass, and every widget.status() call uses them.

widget.prompt()

The paywall meter prompt is a small overlay element that slides in from the left to tell readers how many free articles they have left to view. By default it contains calls-to-action to either subscribe or sign in.

You can turn on the prompt simply by adding this code:

Pigeon.widget.prompt();

You can do further customizations via the settings below.

Settings

promptMeter

type: bool | array
default: true
Specify what meter number to trigger the prompt.

  • true == all
  • false == none
  • array == array of numbers to trigger the prompt e.g., [1,3] will trigger on meter 1 and 3.
copyPage type: array
default: ['page','pages']
The singular and plural form of your content. You may want to use 'article' and 'articles'.
customCopy

type: object
default:

  • title : 'Thanks for visiting!'
  • meterMessage : 'You have %%pigeonMeterAvailable%% %%pigeonCopyPage%% left this month.'
  • lastMeterMessage : 'This is your last page for the month.'
  • subscribeLink : {Pigeon subdomain}
  • signinLink : {Pigeon subdomain}

The Subscribe and Sign In buttons open the Pigeon dialog when clicked. The links are a fallback.

meterCopy

type: object
Change the copy on a particular meter prompt. Each instance uses the customCopy object format. E.g., If you wanted to change the meterMessage for meter 2 it would look like this:

meterCopy:{2:{'meterMessage':'I am changed!'}}

simulate type: bool | integer
default: false
Set any number to overwrite the meter to test what each meter prompt will look like.

Copy Variables

These variables can be used in the meterMessage and lastMeterMessage copy settings.

  • %%pigeonMeter%%
  • %%pigeonMeterLimit%%
  • %%pigeonMeterAvailable%%
  • %%pigeonCopyPage%%

Customize Slider HTML

You can optionally add your own div.pigeon-widget-prompt block to customize the slider. If the pigeon-widget-prompt is not found, the widget renders the HTML for you. Use the following boilerplate code block as your starting point for your own slider layout.

To add a paywall meter prompt to your site, copy the code below and paste it into the footer of your site. The code below serves as a basic starting point, but you can freely modify the HTML and inline styles to match your brand and vision. All ".pigeon-*" class names are required for the prompt to work correctly, but you can rearrange and add to the code as necessary.

<div class="pigeon-widget-prompt" style="display:none; position:fixed; bottom:20px; width:320px; background-color:#fff; box-shadow:0 2px 10px rgba(0, 0, 0, 0.2); overflow:hidden; z-index:999;">
	<div style="background:#f8f8f8; border-bottom:1px solid #eee; padding:10px; position:relative;">
		<span class="pigeon-close" title="Close" style="position:absolute; top:0; right:10px; height:100%; width:18px;">
			<svg style="width:100%; height:100%; cursor:pointer;" fill="#333333" height="24" viewBox="0 0 24 24" width="24"><path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"/><path d="M0 0h24v24H0z" fill="none"/></svg>
		</span>
		<h2 style="font-size:18px; margin:0;">Thanks for visiting!</h2>
	</div>
	<div style="padding:25px 10px; text-align:center;">
		<div class="pigeon-meter-message">You have %%pigeonMeterAvailable%% %%pigeonCopyPage%% left this month.</div>
	</div>
	<div style="border-top:1px solid #eee; text-align:center; font-size:13px;">
		<a class="pigeon-subscribe" href="#" style="display:inline-block; padding:10px;">Subscribe</a>
		<a class="pigeon-sign-in" href="#" style="display:inline-block; padding:10px;">Sign In</a>
	</div>
</div>

Advanced Example

Scenario: A soft paywall with a seven meter limit.

This example will trigger the prompt on meter numbers 1, 3, and 6. Meter numbers 2, 4, 5, and 7 will be skipped. The meterCopy object allows you to customize the message of 1 and 3 in this example. Notice that you can include HTML in the meterMessage string for further customization.

Pigeon.widget.prompt({
	promptMeter:[1,3,6],
	meterCopy:{
		1:{
			meterMessage:'Try us out. You get <strong>%%pigeonMeterAvailable%% free %%pigeonCopyPage%%</strong> for the month!'
		},
		3:{
			meterMessage:'Are you enjoying the content? <strong>Support us</strong> so we can keep serving you.'
		}
	},
	simulate:1 // Change to 3 or 6 to simulate what each looks like
});

Opening the Pigeon Dialog

Use these methods to open the Pigeon dialog from your own buttons and links, e.g. a "Subscribe" button in your site header.

// Subscribe: opens whatever your paywall ruleset leads with (offers page, landing page, or combo)
Pigeon.widget.openSubscribeDialog();

// Subscribe, opened straight on the paid plan options
Pigeon.widget.openSubscribeDialog(null, null, 'plans');

// Sign In
Pigeon.widget.openLoginDialog();
openSubscribeDialog( query, landingPage, jumpTo ) All arguments are optional.
query: object of extra query parameters for the dialog page.
landingPage: a Pigeon page path to open instead of the ruleset's landing page.
jumpTo: the view to open on: 'subscriptions' (default) or 'plans'.
openLoginDialog( query, landingPage ) Opens the same page Subscribe would open, on its sign-in form.

widget.promotionDialog()

The lower-level method behind the dialog. Opens or closes the standard Pigeon dialog, optionally on a specific Pigeon page.

Pigeon.widget.promotionDialog('open');
Pigeon.widget.promotionDialog('close');

// Open on a specific view
Pigeon.widget.promotionDialog({modalAction:'open', jumpTo:'login'});

// Open on a specific Pigeon page
Pigeon.widget.promotionDialog('open', null, 'account');
settings type: string | object
'open' or 'close', or {modalAction:'open', jumpTo:'subscriptions' | 'plans' | 'login'}.
query type: object | null
Extra query parameters passed to the dialog page.
urlPath type: string
default: '/'
Any path on your Pigeon subdomain, or one of these shortcuts: 'account', 'accountEmail', 'accountPassword', 'managePlans', 'register'.

widget.modal()

Opens any page on your Pigeon subdomain in the dialog and keeps links on that page inside the dialog. Use this for pages that have their own flow, such as a registration form.

Pigeon.widget.modal('open', '/path/on/your/pigeon/subdomain');

Advanced: Open a Specific Plan's Registration Page

For technically capable accounts that build their own pricing pages: instead of sending readers to the general offers page, you can open the registration page for one plan, one term, a promotion, or a combo bundle directly in the dialog.

  1. In Pigeon, go to the plan in Plan Manager and copy its permalink. The plan's Profile tab has the plan permalink. Each row on the Terms tab, each promotion, and each combo has its own.
  2. Keep only the path, i.e. everything after your Pigeon subdomain. For example, https://YOUR_PIGEON_SUBDOMAIN/plan/subscribe/abc12/03-annual becomes /plan/subscribe/abc12/03-annual.
  3. Pass that path to Pigeon.widget.modal().

Permalink paths follow these patterns. The first segment is your plan page slug, often plan.

/plan/subscribe/{plan} All terms of one plan.
/plan/subscribe/{plan}/{term} A single term of a plan. {term} is the term's item number, not its numeric ID.
/plan/trial/{plan}/{term} A trial term.
/plan/promo/{promotion} A promotion on a plan.
<a href="#" class="buy-annual">Subscribe annually</a>
<a href="#" class="buy-monthly">Subscribe monthly</a>

<script type="text/javascript">
// Run after Pigeon.paywall()
document.querySelector('.buy-annual').addEventListener('click', function(e){
	e.preventDefault();
	Pigeon.widget.modal('open', '/plan/subscribe/abc12/03-annual');
});

document.querySelector('.buy-monthly').addEventListener('click', function(e){
	e.preventDefault();
	Pigeon.widget.modal('open', '/plan/subscribe/abc12/01-monthly');
});
</script>

Notes:

  • Use widget.modal(), not widget.promotionDialog(), for registration pages. It keeps the reader inside the dialog through checkout.
  • Copy the path from Plan Manager rather than building it by hand. An unknown plan or term opens an empty dialog.
  • To react when a reader finishes or fails checkout in the dialog, see Pigeon.event.registrationSubmit below.

Event

Events help you do more advanced things like tracking click events or metering multiple interactions on a single page.

Pigeon.event.click()

Track and meter click events in Pigeon. The Pigeon Event Meter Limit needs to be set in order to calculate the click event meter correctly. Contact support to set this on your account.

Example

Pigeon.event.click({
	'id':'event-id',
	'title':'Cool Title',
	'restriction':1,
	'ajaxSuccess':function(data){
		console.log(data);
	}
});

Settings

id type: integer or string
Important if the smart meter is on. That way clicks can be remembered for your site visitor. If not set then the click is tracked as an anonymous click.
title type: string
Used as a nice name to view in analytics.
restriction type: integer
default: 0
0 == No restriction
1 == Metered
2 == Full restriction, requires an attached plan to the account
ajaxSuccess type: function( data )
The response callback. The data parameter contains the response variables of the call.
modal type: bool
default: true
Set false if you don't want to trigger the default Pigeon modal. You can trigger your own actions or modal from the ajaxSuccess function above.

Response

allowed type: bool
0 == if access is not allowed
1 == if access is allowed
event_meter_limit type: integer
Total number of unique click events allowed
event_meter type: integer
Total number events used

Pigeon.event.video()

Track video viewing progress in Pigeon analytics.

Pigeon.event.video({
	'id':'video-123',
	'title':'Interview with the Mayor',
	'progress':50 // percent watched
});
id type: integer or string
required
Your unique ID for the video.
title type: string
Used as a nice name to view in analytics.
progress type: number
How much has been watched, as a percent (0-100) or a fraction (0-1).

Pigeon.event.openLinkWithCredit()

Credit scenarios: charge credits for a link to a page or file outside the paywalled site. Pigeon checks access, prompts the reader to spend credits if needed, and opens the URL once access is granted.

Pigeon.event.openLinkWithCredit({
	'url':'https://example.com/report.pdf',
	'title':'Annual Report',
	'value':1 // credits to charge
});
url type: string
required
The URL to open once access is granted.
title type: string
Used as a nice name for the purchase.
value type: integer
default: 1
The number of credits the link costs.

Dialog Event Hooks

Assign your own functions to these hooks to react to what happens inside the Pigeon dialog, e.g. to send a conversion to your analytics.

Pigeon.event.registrationSubmit = function(response){
	if( response.error_message ){
		// The registration or payment failed
	}else{
		// The reader registered or subscribed
	}
};
registrationSubmit( response ) Called when a registration or checkout in the dialog completes or fails. response.error_message is set on failure.
ajaxSuccess( response ) Called after registration, checkout and password reset requests in the dialog.

Account

Pigeon.logout()

Signs the reader out without leaving the page. The optional callback receives the server response.

Pigeon.logout(function(response){
	window.location.reload();
});

OneTrust Consent

For sites using OneTrust cookie consent in a "consent or pay" model: readers who accept tracking cookies can read, and readers who decline are asked to subscribe. Call this before Pigeon.paywall().

Pigeon.oneTrust('enable', {
	ignoreCookieCategories:['C0001','C0003'], // categories that don't count as consent (default)
	conditionalConsent:false
});

Pigeon.paywall({ redirect:'modal' });
ignoreCookieCategories type: array
default: ['C0001','C0003']
OneTrust category IDs that don't count as consent, typically your strictly necessary and functional categories.
conditionalConsent type: bool
default: false
When true, readers who are not subscribers and have access are treated as consenting, and all cookies are allowed.

The OneTrust banner is hidden; the Pigeon dialog takes its place for readers who have not consented. Readers who have consented skip the paywall. For signed-in subscribers with access, Pigeon rejects tracking cookies, since they have paid instead.

Schedule
a Demo