Does your site have a standard WordPress setup? Get up and running in a minute by installing the Pico WordPress plugin: Install on WordPress.

If you're not using WordPress (or if you have a headless WordPress setup), you can install Pico by following the 3 steps below. Before getting started, please make sure that you have a your Primary URL saved in your account's Website settings at Settings > Website. If you have a Staging URL and/or Development URL, you will need to save those as well in order for Pico to successfully load on those versions of your site.

⚠️ NOTE: The installation method below requires development knowledge and the ability to manage the code on your side. This should be for advanced users only. Please contact Pico support if you need assistance or would like a recommendation for a Pico Developer Partner.

1. Install the Gadget Snippet

The Gadget snippet for installation on your site is automatically generated for your account under the Settings > Website section. You should then insert this block in the <head> section of your website.

Alternatively, you can copy the following JavaScript snippet and paste it inside the <head> code of your website.

⚠️ NOTE: Replace INSERT YOUR ACCOUNT ID in the snippet with your Pico Account ID which you can find under the WordPress section of the Apps settings at Do not remove the quotation marks surrounding the Account ID.

(function(p,i,c,o){var n=new Event("pico-init");i[p]=i[p]||function(){(i[p].queue=i[p].queue||[]).push(arguments)},i.document.addEventListener("pico-init",function(e){var t=i.Pico.getInstance(e,{publisherId:o,picoInit:n},i);t.handleQueueItems(i[p].queue),i[p]=function(){return t.handleQueueItems([arguments])}},!1);var e=i.document.createElement("script"),t=i.document.getElementsByTagName("script")[0];e.async=1,e.src=c,e.onload=function(e){return i.Pico.getInstance(e,{publisherId:o,picoInit:n},i)},t.parentNode.insertBefore(e,t)})("pico",window,"", "INSERT YOUR ACCOUNT ID");

2. Send information about each page to Pico using the Page Properties Snippet

Copy the following JavaScript snippet and paste it before the closing </body> tag of each page. (We recommend inserting it as the last element before the closing </body> tag.) On each page of your site, set a value for each of the properties in the snippet.

var pageInfo = {
article: bool,
post_id: string,
post_type: string,
resource_ref: unique_reference_string, // optional
taxonomies: { tags: [...], categories: [...], some_custom_taxonomy: [...] },
url: window.location.href

window.pico('visit', pageInfo);

Here's a sample of what the code looks like with values filled in:

var pageInfo = {
article: true,
post_id: "e940fd16-b7cd-11ea-b3de-0242ac130004",
post_type: "article",
taxonomies: { tags: ["red","blue"], categories: ["primary-colors"]},
url: window.location.href

window.pico('visit', pageInfo);

These values will need to reflect the content of your site rather than be shared globally across all posts. For example, in the code snippet above, this lists the tags "red" and "blue," but there may be sections of your site that you'd like to tag "yellow" or not tag at all so that they wouldn't be behind paywalls. Learn more about tagging content in Pico.

Installing on a Single Page App (SPA)?

For most SPAs, Pico works without additional configuration.

On route change, you'll need to simulate the window.pico('visit', pageInfo); call as if it were a new page load. Be sure to re-populate the pageInfo object before making the call with the new "page" information.

Installing on a Common CMS?

Depending on your content management system (CMS), you may be able to auto-populate the tags for pages on your site using JavaScript so that you can insert the pageInfo code globally across your site and let the CMS fill in the correct values. We've provided an example for Squarespace,, and

Required Properties

article boolean

  • true if this is a post, article, story, or something equivalent. Note: a page must have article set to true to be subject to regiwall or paywall settings.

  • false if this is a contact page, taxonomy index, section/topic index of posts, or generally, a page that would never have content set behind a regiwall or paywall.

  • This value will determine whether or not we can track taxonomy info. We only track what your visitors are reading based on the taxonomies being passed and only when article is true.

post_id string

  • A unique string post identifier. We use this to uniquely identify whether something has been read by a user or not. We recommend using a UUID here. Some CMSs will provide this for you or you can use the URL of the article.

post_type string

Below are recommended post types. If you want to refer to a “post” as a “story” instead, go for it! Just make sure that the article boolean is set appropriately for each content type.

  • home

  • post

  • page

  • author

  • category

  • tag

  • tax

  • search

  • date

  • 404

taxonomies object

  • An object with keys of taxonomy types and values of arrays.

  • Requires article to be true in order to track reader activity (i.e. this user likes to read posts with the category of "pets").

  • In the example below, we are passing three taxonomy objects of tags, categories, and some_custom_taxonomy — each with an array of values.
    taxonomy types

Example value:

"cute things"

Note: You will also need to add the custom taxonomy to the integrations tab in your account settings under Settings > Website.

url string

  • The current URL

Example value:


Optional Properties

resource_ref string

  • Unique string identifier ie:

Example value:


3. Wrap page content for things you want to be considered lockable

For pages that are article: true, wrap content in <div id="pico"></div>.

<div id="pico">
<p>Content you want to track users reading.</p>
<p>Potentially limit access based on whether readers are registered and/or paying.</p>

The <div id="pico"></div> should contain multiple immediate children elements so that locked content can show a small preview and hide everything else.

4. Taking Pico Further

Once you've confirmed that the basics are up and running, we've provided a list of helpful next steps and best practices to consider for developers:

Helpful tips

A note on infinite scroll and dynamic routing sites

If you have a site where each page load has all of the needed information for the Pico tracking snippet, autotracking works fine.

If you have a single page app that uses something like react-router to navigate from page to page (where the app manages the URL and view without a full app refresh), you will need to hydrate that info on each page view about the current URL. This means autotracking is incompatible with your site. No problem! Just make sure you insert a Pico tracking snippet that is called to track every navigation event a user takes, otherwise, you won’t see more than the initial app load info.

This will also need to be handled on websites with infinite scroll (where the URL changes as you scroll).

A note on staging sites and test environments

At this time, we don’t provide a separate sandbox account ID for you to use on your staging or test environment. We allow you to use the same account ID for testing your integration on your non-production website. Therefore any users created while testing your integration will need to be manually removed from your CRM to ensure you aren’t being billed for that record.

Did this answer your question?