User Manual Quickstart General Concepts Frame Features Resources Style Reference Change Log Glossary Acknowledgements Api Reference Authorization Tokens Embedding The Editor Attaching the editor Forwarding the visual viewport Listening to callbacks Form Fields Custom Integration Backend Api

Embedding the Printess Editor (iframe-ui)

Printess editor can easily embeded as an iframe to your shop or web-site:

<iframe  id="printess" src="https://editor.printess.com/printess-editor/embed.html"></iframe>

Tip: In the User Menu (top right corner) you’ll find the option Embed Code. Just click on it and you’ll get a ready made piece of html code for pasting the current template into any HTML page.

User menu

In the Printess Github Repo you can find a simple example how to integrate the Printess editor. It also contains the proper styling for the iframe.

It’s highly recommended to show the Printess editor iframe in full-screen. Especially on mobile the user experiences gets quirky if other elements are shown on top or below the editor. Space is extremly limited and to achive the app-feeling scrolling of the website should not happen. When iOS is expanding its giant on-screen keyboard Printess will counter act this by hiding all toolbars and page navigation. And when the keyboard collapses Printess will get back to normal as well. This will only work if your page does not exceed the area of the iframe.

If you like to handle this behaviour on your own and want to tweak the existing code, please have a look at the custom integration down below.

Attaching the editor

Once the DOM is loaded you will need to pass some essential parameters, like your shop-token, the name of the template and your session or basket ID.

iframe.contentWindow.postMessage({
    cmd: "attach", properties: {

      /* Paste your Printess shop-token here */
      token: "", 
      
      /* Name of the template to load. You can also pass a save-token from "basket" or "back" callback here to load previously saved work. */
      templateName: "Greeting Card", 

      /* Version of the template. Can be draft or published (default) depending on which version of the document should get used */
      templateVersion: "published" 
      
      /* A unique ID to identify this session, can later be used to connect to a UserID once the user has logged in or created an account */
      basketId: "Some-Unique-Basket-Or-Session-Id",

      /* Optional if available: the ID of the current shop-user to keep all uploaded resources together and display for reccuring users */ 
      shopUserId: properties.shopUserId,
      
      /* Optional: you custom CSS or a Bootstrap Theme */
      cssUrl: window.location.origin + "/bootstrap-themes/sketchy.css", 

      /* Optional: A list of templates to merge on load */
      mergeTemplates: [
        {
          "templateName": "Card-Title-2",
          "spreadIndex": 0  // Example to merge a card title to the first spread on load 
          "templateVersion": "published" // Can be draft or published (default) depending on which version of the document should get used
        },
        {
          "templateName": "Card-Back-2",
          "spreadIndex": 2  // Example to merge a card back to the third spread on load 
          "templateVersion": "published" // Can be draft or published (default) depending on which version of the document should get used
        }
      ],

      /* Optional: Add your own translation-table. */
      translations: {
        "custom": {
          "name": "Your Name" // you can access this translation with ${gl("custom.name")}
        },
        "ui": {
          "okButton": "Perfect!"
        }
      },

      /* Optional: A list of Form Fields which will be pre-filled on load */
      formFields: [
        {
          name: "Name",
          value: "Peter Meyer"
        },
        {
          name: "Email",
          value: "peter.meyer@printess.com"
        }
      ]
    }
  }, "*");
}

token

 token: 'YOUR TOKEN'

token should be set to a Shop-Token which points to your Printess Account. You can get this token once you are logged in in the Printess Editor -> Account Menu -> API-Token. You’ll see 2 different tokens in the dialog. Please always use the Shop-Token.

templateName

templateName: 'Sign'

templateName is required and specifies the name of the template to load.
templateName can also take the save-token you received from back or basket callback and load it directly.

basketId and shopUserId

To enable your customer to upload images and to save or load the state of work - you need to set the basketId.

Optionally you can set a shopUserId to make Printess store in the context of the current customer (user). Also when the customer uploads an image it will be stored under the shopUserId. So if the customer returns later he or she will see its previous uploaded images.

cssUrl

The Printess buyer UI is build on bootstrap. So you can easily pass the URL to a bootstrap-theme-css like the once you’ll find on https://bootswatch.com

You can also add your own CSS to that call. The Printess UI is based on bootstrap and some custome styles found in our github repo: bs-layout.css

mergeTemplates

templateName: "card",
mergeTemplates: [{
  templateName: "motive1",
  documentName: "Document", // optional, if not supplied Primary or first Document is used
  spreadIndex: 0; // optional
}];

A comonly used approach is to have a master-template with the final dimensions and all the general buyer side settings and the available colors and fonts. And then having multiple artwork-templates which the customer can select directly from the shop-catalog. Lets say the master-template’s is named card and the selected motive’s name is motive1. If you show the Printess editor you can now load card via the templateName property and merge in the document Document from template motive1 via then mergeTemplates property.
In spreadIndex you can define spread number where the merged template is placed on. It’s zero based and please keep in mind that on a facing-pages document each pair of pages counts only as a single spread.

translations

translations: {
  "custom": {
    "name": "Your Name" // you can access this translation with ${gl("custom.name")}
  }
}

Printess provides an internal translation-table to display the buyer UI in different languages. The buyer side language for the individual templates can be set in the Template Preferences. If it is set to auto, the buyer UI will be displayed in the system language of the user, provided that the translation is available.

To customize the text content of the Printess buyer UI you can add your own translation-table to the attachPrintess call. You will find all available keys in the translation.json on the Printess Github Repo. You can modify the values to the given keys to your needs by adding them to your own translation-table. If no custom translation is found, Printess’ fallback translation will be searched through.

Forwarding the visual viewport

Unfortunately iOS does not let an iFrame receive visual-viewport events or values, so we need to forward it.

The visual-viewport is needed to identify if the software-keyboard is visible on iOs and to move the selected frame in the center of the remaining screen. So if you observe any behaviour where the text scrolls off screen while you editing it, it’s propably because the “viewportScroll”-Event has not been forwarded.

    if (window.visualViewport) {
      window.visualViewport.addEventListener("scroll", () => {
        iframe.contentWindow.postMessage({ cmd: "viewportScroll", height: window.visualViewport.height, offsetTop: window.visualViewport.offsetTop }, "*")
      })
    }

Listening to callbacks

To continue the shopping journey Printess will give you two essential callbacks:

back, when the users presses the back button

basket when the user wants to continue buy the configured product

Both callbacks give you a so called save-token which you can store in your database and later use to either print the saved configuration or load the saved work again to the Printess editor and allow the users to continue their work.

window.addEventListener("message", () => {
  switch (event.data.cmd) {

    case "back":
      alert("Back to catalog. save-token:" + event.data.token);
      break;

    case "basket":
      alert("Proceed to checkout. save-token:" + event.data.token + " thumbnailUrl:" +event.data.thumbnailUrl);
      break;

    case "formFieldChanged":
      alert("Price Relevant Form Field: [" + event.data.name + "] changed to '" + event.data.value + "'");
  }
});

Back-Callback

Is fired when the users clicks on the back button. It carries a save-token in case you want your user allow to continue the work later. Just pass the save-token instead of the template name.

Basket-Callback

Is fired when the user clicks on the “Add to Basket” button. It carries a save-token which you can later pass to the backend API for production or pass to templateName for making changes on the saved work. The basket callback also carries a thumbnail URL in case you want to show the configured product in your shopping cart.

Form Fields

Printess has the concept of Form Fields which can be created by the designer and changed by the buyer.

Passing Form Field Values

Lets say you want to pre-populate form fields with customer data when showing the printess editor, you can do it like so:

formFields: [
  {
    name: "Name",
    value: "Peter Meyer"
  },
  {
    name: "Email",
    value: "peter.meyer@printess.com"
  }
]

Just pass an array of objects during when loading the Printess editor. Each object needs to address a form-field by its name and set its value as string. Even if the form-field type is number or object, you need to pass the value as a string. The above example could be the pre-population of a business card template.

Receiving Form Field Updates

A third callback is formFieldChanged which is helpful if the user changes certain configuration which has been marked as price relevant. Depending on the resulting value you can adjust the price of the product.

Those Form Fields can contain information which are price relevant like material or color. The Retro Sign template from our examples exposes a couple of such Form Fields. Material, Size - and if a solid material is selected - Drill Holes and Varnish. All 4 Form Fields are possibly price relevant so the eCommerce application must know if any of this values has been changed.

Congratulations!

You now know everything to get started with the Printess Editor. Have fun and please let us know what you like and where we could have done better.