This article details how to install Pico onto a Squarespace site and programmatically include tagging/category values from blog posts. It also includes instructions on customizing the page content that Pico puts behind registration or paywalls, without needing to change the page template in Squarespace.

Populating Tags, Categories, and Post Type
While the majority of the Pico installation code can be pasted once into the head of the website code, we require certain pieces of data to enable features like locking articles by tag or category. Rather than requiring custom javascript for every page, which can become unmanageable for sites using Squarespace's blog functionality for new possible, it's possible to inject the tags and categories that are populated in Squarespace, into the Pico snippet. This pertains mostly to the post_id  and taxonomies values.

Step 1 - Install the Global Pico Code
The main Pico snippet should be loaded on all pages, and any non-blog posts should have the pageInfo object entered with manual values (including the main blog landing page).  The main snippet can be copied into the Settings > Advanced > Code Injection section. The pageInfo object should be loaded into the Code Injection for each specific page. This method should only be necessary for the Home Page, About, or other main pages on your site.

For more information on installing the required javascript in general, review our Pico Installation guide.

Step 2 - Install the Code in Blog Posts to Automatically Read from Squarespace tags
In the code below, the post_id and taxonomy are populated based on what is set for the post in Squarespace. This should be pasted into the Advanced > Page header Code Injection section of the main Squarespace blog page. It will then load on each blog post, pulling the tag and category values set within Squarespace.

<script>
function setupPicoVisit(pageData) {

    if(typeof window.pico !== 'undefined' && typeof pageData === 'object') {

        var pageInfo = {
          article: true,
          post_id: pageData.item.id,
          post_type: 'post',
          taxonomies: { tags: pageData.item.tags, categories: pageData.item.categories },
          url: pageData.website.baseUrl + pageData.item.fullUrl
        };
        window.pico('visit',pageInfo);

    }

}

function onSQSItemLoaded() {
  setupPicoVisit(JSON.parse(this.responseText));
}
 
var httpRequest = new XMLHttpRequest();
if (!httpRequest) {
  console.log('Giving up :( Cannot create an XMLHTTP instance');
}
httpRequest.addEventListener("load", onSQSItemLoaded);
httpRequest.open('GET', window.location.origin + window.location.pathname + '?format=json-pretty');
httpRequest.send();

</script>

Visit https://pico-example.squarespace.com/ to see this implemented on a demo Squarespace site.

Wrapping the "Pico Div" around Content (Optional)
To support the content preview Pico shows on registration- or pay-walled pages, Pico requires that all hideable content exists in the page structure inside a <div id="pico"> container. If you don't want to change the page templates on your site, you can create this using javascript. The code below shows an example, with a timeout delay to make sure the site content is loaded before firing the Pico events (which trigger registration or payment walls).

This assumes that the page content exists in a div already labeled with the id of "page". To wrap other content on the site, replace the definition of var el at the bottom.
Note: In this example the window.pico('visit', pageInfo);  line is within the waitUntil method and should only be loaded once on the page. The javascript that defines that pageInfo object (listed earlier in this article) is still necessary.

  <script>
/**
 * @brief Wait for something to be ready before triggering a timeout
 * @param {callback} isready Function which returns true when the thing we're waiting for has happened
 * @param {callback} success Function to call when the thing is ready
 * @param {callback} error Function to call if we time out before the event becomes ready
 * @param {int} count Number of times to retry the timeout (default 300 or 6s)
 * @param {int} interval Number of milliseconds to wait between attempts (default 20ms)
 */
function waitUntil(isready, success, error, count, interval){
    if (count === undefined) {
        count = 300;
    }
    if (interval === undefined) {
        interval = 20;
    }
    if (isready()) {
        success();
        return;
    }
    // The call back isn't ready. We need to wait for it
    setTimeout(function(){
        if (!count) {
            // We have run out of retries
            if (error !== undefined) {
                error();
            }
        } else {
            // Try again
            waitUntil(isready, success, error, count -1, interval);
        }
    }, interval);
}

$( document ).ready(function() {
var el = '#page';
  $(el).wrapAll('<div id=pico></div>')

waitUntil(function(){
      return $('#pico').length > 0;
  }, function(){
      window.pico('visit', pageInfo);
  }, function(){
  });
</script>


Did this answer your question?