Sending Clickwrap Data Server-side

You may want to use PS.js to render the contracts on the page, populate a contract with app data, and more—but send the API call on the back-end. Here's how to do it!


In this article, we'll cover how you can use the JavaScript library in tandem with our API to send acceptance of a contract or contracts on the back-end. You'll learn how to:

  • Load PS.js and render the contract on the page
  • Set the Signer ID of the signer programmatically
  • Disable sending when the checkbox on a click-through agreement is clicked
  • Send the payload that would be sent automatically to your back-end.


In order to complete this article, you'll need the following already working:

  • A published Contract that's been marked "Public" and added to a Group
  • A published Group with a Group Key
  • Working knowledge of JavaScript

When to Use

By default, when you load an embedded contract onto a page, we'll automatically send acceptance of a contract as soon as your signer checks the box. Some people don't want to do this, so we've got a couple of different ways to handle sending acceptance. Below you can see our proposed flow for:

  1. Loading PS.js and embedding the contracts into your page, which will dynamically grab the right contracts and versions and inject them into the page.
  2. Send acceptance after a user completes the form using the Activity API.

Load the Embedded Clickwrap

To get the contract loaded into your page, simply use the snippet below and swap out with your own Site Access ID (found here) and your Group Key (found in your Group):


Example Only Code

Please note that the example code is for demonstration purposes only. Your implementation will most likely be different than what is shown here.

// Minified Clickwrap Snippet
(function(w,d,s,c,f,n,t,g,a,b,l){w['PactSafeObject']=n;w[n]=w[n]||function(){(w[n].q=w[n].q||[]).push(arguments)},w[n].on=function(){(w[n].e=w[n].e||[]).push(arguments)},w[n].once=function(){(w[n].eo=w[n].eo||[]).push(arguments)},w[n].off=function(){(w[n].o=w[n].o||[]).push(arguments)},w[n].t=1*new Date(),w[n].l=0;a=d.createElement(s);b=d.getElementsByTagName(s)[0];a.async=1;a.src=c;a.onload=a.onreadystatechange=function(){w[n].l=1};a.onerror=a.onabort=function(){w[n].l=0};b.parentNode.insertBefore(a,b);setTimeout(function(){if(!w[n].l&&!w[n].loaded){w[n].error=1;a=d.createElement(s);a.async=1;a.src=f;a.onload=a.onreadystatechange=function(){w[n].l=1};a.onerror=a.onabort=function(){w[n].l=0};b.parentNode.insertBefore(a,b);l=function(u,e){try{e=d.createElement('img');e.src=''+w[n].t+'&u='+encodeURIComponent(u);d.getElementsByTagName('body')[0].appendChild(e)}catch(x){}};l(c);setTimeout(function(){if(!w[n].l&&!w[n].loaded){w[n].error=1;if(g&&'function'==typeof g){;}l(f)}},t)}},t)})(window,document,'script','','','_ps',4000);

// We'll need a couple of things to get started from Clickwrap.
var siteAccessId = "1e8ddd9d-f32c-4dc7-9c13-62095e6d4317"; // A Clickwrap Site Access ID
var groupKey = "clickwrap-example"; // A Clickwrap Group Key.

// Creates a Site object with the a Clickwrap Site Access ID.
_ps("create", siteAccessId, {
  disable_sending: true // Disable automatic sending with the JavaScript snippet.
  test_mode: true // Allows you to clear test data from the Ironclad Clickwrap web app.

// Load a Clickwrap group into the page.
_ps("load", groupKey);

Send Acceptance Server-side

The best way in accomplishing this is by grabbing the payload (outlined below) and then sending it with whichever client you'll be using on the backend. See the example below for one approach.


Example Only Code

Please note that the example code is for demonstration purposes only. Your implementation will most likely be different than what is shown here.

// Grab the payload (encoded URL params) to be sent once accepted and ready.
const myPayload ='clickwrap-example').getPayload();

/// ...
// The Backend receives the data from a hidden input field or some other mechanism

// Let's pretend we are using a node server that received the payload.
const fetch = require('node-fetch');
(async (myPayload) => {
  const response = await fetch('' + myPayload, {
    method: null,
    headers: {'Content-Type': 'application/json'}
  const json = await response.json();

What’s Next

Get more dynamic in how you load and track acceptance on embedded contracts: