Adobe
Products
Acrobat
Creative Cloud
Creative Suite
Digital Marketing Suite
Digital Publishing Suite
Elements
Photoshop
Touch Apps
Student and Teacher Editions
More products
Solutions
Digital marketing
Digital media
Education
Financial services
Government
Web Experience Management
More solutions
Learning Help Downloads Company
Buy
Home use for personal and home office
Education for students, educators, and staff
Business for small and medium businesses
Licensing programs for businesses, schools, and government
Special offers
Search
 
Info Sign in
Welcome,
My cart
My orders My Adobe
My Adobe
My orders
My information
My preferences
My products and services
Sign out
Why sign in? Sign in to manage your account and access trial downloads, product extensions, community areas, and more.
Adobe
Products Sections Buy   Search  
Solutions Company
Help Learning
Sign in Sign out My orders My Adobe
Preorder Estimated Availability Date. Your credit card will not be charged until the product is shipped. Estimated availability date is subject to change. Preorder Estimated Availability Date. Your credit card will not be charged until the product is ready to download. Estimated availability date is subject to change.
Qty:
Purchase requires verification of academic eligibility
Subtotal
Review and Checkout
Adobe Developer Connection / Digital publishing /

Build a custom storefront

by Scott Dreier

Scott Dreier

Content

  • Getting started
  • Example
  • JavaScript Viewer API for Digital Publishing Suite
  • Connecting to fulfillment
  • Development and maintenance considerations
  • Where to go from here

Created

5 March 2012

Page tools

Share on Facebook
Share on Twitter
Share on LinkedIn
Bookmark
Print
Digital Publishing Suite

Requirements

Prerequisite knowledge

This article assumes knowledge of JavaScript, HTML and XML and Adobe Digital Publishing Suite.


Additional requirements

  • JavaScript Viewer API for Digital Publishing Suite 
  • Find links to the latest Folio Builder panel and Folio Producer tools from the Digital Publishing Suite dashboard at http://digitalpublishing.acrobat.com

User level

Intermediate

Required products

  • InDesign CS5 (Download trial)
  • Digital Publishing Suite, Enterprise Edition

Sample files

  • example_devnet.zip
  • Custom_store_templates.zip
  • JS Bridge API (zip file for offline viewing only)

Note: If you have questions about this article, use the comments feature at the bottom of the article. Please don’t contact technical support with questions about Adobe Developer Connection articles.

A Digital Publishing Suite viewer application optionally can contain a number of custom navigation slots beyond the standard "Library" and "Viewer". These slots implement webviews for rendering of HTML5, CSS3, and JavaScript. Each of these slots has its DOM modified at run time to provide a bridge to services exposed by the application. These services are detailed in the JavaScript Viewer API for Digital Publishing Suite. By using these services, a publisher can create a custom, branded and highly designed merchandising view to present folio or other digital content for sale. The webpage is hosted by the publisher and loaded at runtime allowing the use of server technologies (PHP, JSP, CMS). Publishers are free to create any visual design or technical functionality of their choosing; however, for purposes of this article we assume a merchandising view of Digital Publishing Suite folio content available for in app purchase.

This article will cover the basics for creating a custom storefront.

Note: Only Digital Publishing Suite Enterprise Licensees can add Custom Navigation slots.

Figure 1: Custom Stores can include animated banners to capture and retain visitor attention.
Figure 1: Custom Stores can include animated banners to capture and retain visitor attention.
Figure 2: Publishers can include cross-sell or upsell offers, like a subscription call-to-action, to drive incremental revenue.
Figure 2: Publishers can include cross-sell or upsell offers, like a subscription call-to-action, to drive incremental revenue.

Getting started

You implement custom storefront code using HTML5, CSS3, and Javascript in conjunction with the Javascript Viewer APIs for DPS. You package your custom storefront with your application when you create a viewer application using Viewer Builder. Specifically, you provide an archive (zip) file of the code that implements your storefront as the "Icon xxx HTML Resources ZIP".

  1. Your archive must contain an index.html file. This will be the top level of your store.
  2. Your archive should be flat. All files should be in the same folder.
  3. Only include files that are unlikely to change. Load all others at runtime through HTTP.

Initialization

Your code can only begin using the JavaScript Viewer APIs after receiving the onadobedpscontextloaded event from the window object. To ensure that no method calls are used before they should be, postpone any initialization until this event is received.

$(document).ready(function() { var init = function() { // Define a function in case the main JavaScript file has not loaded yet. if (!window.onnetworkconnection) { window.onnetworkconnection = function() { window.connected = true; } } } if (navigator.userAgent.toLowerCase().indexOf("ipad") == -1) { // On desktop so call init() immediately. init(); } else { window.onadobedpscontextloaded = init; } });

The above code initializes based upon whether the code is executing within the iPad or within a desktop browser (Safari on a Mac). The latter being very useful for development purposes. After init() has been executed, it is safe to begin store operations.

Existing folios

Check for the presence of existing folios using the getFolioData() and updateLibrary() methods. The getFolioData() retrieves an array of folio descriptors known to the Viewer's library. Valid folioState values:

folioState value

Description

0

Invalid

50

Unavailable. The folio is not yet available for purchase

100

Purchasable. Can be purchased and downloaded

101

Purchasing. There is an active or paused Purchase Transaction for the folio

200

Downloadable. The folio is free, or its Purchase Transaction completed

201

Downloading. There is an active or paused Download Transaction for the folio.

400

Extractable. The folio content is stored locally.

401

Extracting. There is an active or pause Extraction Transaction for the folio.

1000

Viewable. The folio is can be loaded in the viewer.

1500

Update available. The folio is viewable but can be updated.

1501

Downloading update. There is an active update download for this folio

1502

Update extractable. The folio is viewable but has an update that can be installed.

1503

Extracting update. There is an active update extraction for this folio.

Buying (or viewing) folios

There are two methods for initiating the purchase: download and/or viewing of a folio.

Method

Description

buyFolio

Initiates the eCommerce with the AppStore to begin purchase of a folio. Actual purchasing is all handled by the viewer, AppStore and iOS. Once complete, the application will present it's Library view and the folio will start downloading.

viewFolio

Initiates the download and/or viewing of a Folio. If the folio has been published as FREE, then it is downloaded. Once the folio has been downloaded, calling viewFolio() will open the folio for viewing within the viewer application.

For RETAIL folios, pricing information from iTunesConnect are contained within the folio description objects returned from getFolioData().

Example

Let's walk through an example of a basic storefront. This example showcases the JavaScript required to implement a storefront. The templates provide basic implementations. This example will walk through:

  1. Check for network connectivity.
  2. Wait for the API to be available.
  3. Request an update of the library.
  4. Create a visual representation of the folio and a button to purchase it.
  5. Download (or purchase) and view a folio.

Setup

  1. Download the source archive.
  2. Create a multi-issue viewer. Customize the navigation toolbar with a custom icon. Use the archive file (example_devnet.zip) as the archive for the "Icon xxx HTML Resources.zip" resource.
  3. Create a folio and publish it as PUBLIC/FREE with the product ID storefolio1.
Network_detection.js
$(document).ready(function() { var init = function() { // Define a function in case the main JavaScript file has not loaded yet. if (!window.onnetworkconnection) { window.onnetworkconnection = function() { window.connected = true; } } } $.ajax({ type: "GET", url: "http://www.google.com", success: function() { window.onnetworkconnection(); }, error: function() { $("body").append("<div id='offline'>You must be connected to the Internet to access the store.</div>"); } }) if (navigator.userAgent.toLowerCase().indexOf("ipad") == -1) { // On desktop so call init() immediately. init(); } else { window.onadobedpscontextloaded = init; } });

The above file first uses JQuery's .ajax function to fetch a well known web address to determine if the device is currently on-line. If successful, it sets a property window.connected for later inspection.

basic_store1.js


You implement the core of this example in the basic_store1.js file.

First, define the productID we will be offering for purchase/download.

var productID = 'storefolio1';

The next block of code sets up callback for receiving notification upon an update library event. Whenever the library is updated, the code fetches descriptions of all the folios in the account. Depending upon the state 'folioState' of the folio, the label on the purchase button is set to "Buy", "View" (for downloaded or free content), or "Invalid" (shouldn't happen).

var onFolioData = function (data) { var len = data.length; // The library returns an array of folio descriptor objects. Put them into a hash indexed by something more convenient (ie productId) for (var i = 0; i < len; i++) { folioDataHash[data[i].productId] = data[i]; console("Folio: "+data[i].productId); } var folio = folioDataHash[productID]; if (folio) { // Also fetch our preview image. adobe.dps.store.getPreviewImage(productID, true, 768, 1024, onPreviewImage); } else { console("The productId you have defined for purchase/download does not exist within your Fulfillment account"); } }; var onPreviewImage = function(data) { var s=""; var folio = folioDataHash[productID]; if (!folio) return; // un-known folio...nothing to show. //// // At this point, we have valid folio data representing our folios and a folio image for our target product ID. //// // Create the image s += "<img src='"+data['path']+"' width='160' height='222' />"; // Create the Title s += "<div id='title'>"+folio.title+"</div>"; // Create the Folio Number s += "<div id='manifestXRef'>"+folio.description+"</div>"; // Create the buy|view button and then create the 'buy' or 'view' label and assign a click handler, if valid s += "<div class='buyButton' id='buyButton1'>"; if (folio.folioState=='100') { // buy folio s +="Buy"; } else { s += "View"; } s += "</div>"; var node = document.getElementById("ourItem"); if (node) { node.innerHTML = s; node.onclick = node.onclick=buy; } }; var onLibraryUpdate = function () { adobe.dps.store.getFolioData(onFolioData); // Unregister for library updates unregisterUpdateLibraryHandler(); } var registerUpdateLibraryHandler = function () { if (window.adobedpscontextloaded) { // call into the updateLibrary API adobe.dps.store.registerLibraryUpdateCompleteHandler(onLibraryUpdate); adobe.dps.store.updateLibrary(); } else { console("Failed to find Javascript API"); } }; var unregisterUpdateLibraryHandler = function () { if (window.adobedpscontextloaded) { // call into the updateLibrary API adobe.dps.store.unregisterLibraryUpdateCompleteHandler(onLibraryUpdate); } } registerUpdateLibraryHandler();

JavaScript Viewer API for Digital Publishing Suite

Previously referred to as "Custom HTML Store" or "Store APIs", the JavaScript Viewer API for Digital Publishing Suite provides a bridge between web pages hosted within a custom navigation slot or entitlement banner. Both areas have access to the same functionality. However, pages opened (the 'slide-up webview') by either the entitlement banner or the custom navigation slot, do not have access to these APIs.

The JavaScript Viewer API for Digital Publishing Suite provides access to:

  1. eCommerce features within the viewer application. The code can initiate transactions to purchase individual folios or subscriptions.
  2. Introspection of folio descriptions within the library.
  3. Retrieve and set authentication for a specific user (entitlements only).
  4. Access to cached versions of the cover images displayed in the library.
  5. Entitlement information for folios.

The API is an asynchronous interface. This means you must provide callback handlers to receive content at future time, as in the following example:

adobe.dps.store.getFolioData(onFolioData);

The getFolioData() method passes a reference to the onFolioData() method. When the folio data has been collected by the viewer, it will invoke the callback onFolioData() and provide an array object containing the data.

Note: At the time of this writing (v19), the JS API can only support a single outstanding callback at a time. You should serialize all operations and ensure to have only a single outstanding callback active at any one time.

Connecting to fulfillment

The examples included with this article fetch information about all available folios directly from the viewer. The viewer gets this information from your Adobe Fulfillment account. This account contains your published, public content. When you develop your storefront on a desktop or test within a browser, you can access this data from the fulfillment server.

It remains a best practice to allow only the viewer to fetch this data – and to have the storefront code fetch it from the viewer (with a call to getFolioData). Not only does this pattern eliminate potentially costly and redundant web calls, it also ensures that the correct and consistent rendition logic is applied to the folio list.

The following steps help you access your fulfillment account if you are required to.

Each Adobe ID references a specific Adobe Digital Publishing Suite fulfillment account. Likewise, every magazine application pulls folios from a specific Adobe Digital Publishing Suite fulfillment account. Fulfillment accounts are identified by a GUID (for example, 943864f0a0d2431aa2992987caf78cb0).

For applications that want to create a customized view of their folios, access the data within the fulfillment account can be very useful.

To access your fulfillment account associated with your Adobe ID (or your magazine's AdobeID), you need to discover your GUID. This can be found by inspecting the LibraryConfig.plist file within your application's contents, as follows:

  1. Locate your IPA file produced and downloaded by Viewer Builder.
  2. Open with an Archive utility.
  3. Locate the Application file (for example, viewer.app) and control-click to choose "Show Package Contents".
  4. Within the file LibraryConfig.plist, the value at serviceOptions->fulfillment->loginOptions->accountId is your GUID.
Figure 3: LibraryConfig.plist
Figure 3: LibraryConfig.plist

You can then retrieve an XML description of all the public folios within your fulfillment account at the following URL:

http://edge.adobe-dcfs.com/ddp/issueServer/issues?accountId=<your GUID>&targetDimension=1024x768,768x1024,1024x748,748x1024

or:

http://edge.adobe-dcfs.com/ddp/issueServer/issues?accountId=<your GUID>&targetDimension=all

for example:

http://edge.adobe-dcfs.com/ddp/issueServer/issues?accountId=b8c8d8164adb4dcf8e69e94fae1c58f6&targetDimension=1024x768

The following is an example response containing a single folio:

<results status="SUCCESS" message="Success"> <issues> <issue id="bdfb4254-1276-4393-abc6-3578540b750e" productId="look14" formatVersion="1.7.0" version="4" subpath=""> <magazineTitle>Daily Fashion</magazineTitle> <issueNumber>14</issueNumber> <publicationDate>2011-05-01T07:00:00Z</publicationDate> <description>bracelet</description> <manifestXRef>May 2011</manifestXRef> <state>production</state> <libraryPreviewUrl landscapeVersion="1" portraitVersion="1">http://edge.adobe-dcfs.com/ddp/issueServer/issues/bdfb4254-1276-4393-abc6-3578540b750e/libraryPreview</libraryPreviewUrl> <brokers> <broker>noChargeStore</broker> </brokers> </issue> </issues> </results>

Note: Multiple <issue> nodes will probably exist.

Accessing Cover images from your fulfillment account

Within the XML returned from fulfillment, each <issue> node contains a <libraryPreviewUrl> element. Use this URL with either portrait or landscape appended to access your images.

Eg. http://edge.adobe-dcfs.com/ddp/issueServer/issues/bdfb4254-1276-4393-abc6-3578540b750e/libraryPreview/portrait

Development and maintenance considerations

While all the code for a store implementation can be embedded within the viewer, this makes updates to the code dependent upon updates to the viewer. Instead, only code that is not likely to change (JQuery.js) should be included. Also, the archive you provide to Viewer Builder for inclusion must contain an index.html file. Keep this simple.

From our example:

<html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Banner</title> <script src="jquery-1.5.min.js"></script> <script src="network_detection.js"></script> <script src="basic_store1.js"></script> <link rel="stylesheet" href="offline.css" type="text/css"> <link rel="stylesheet" href="styles.css" type="text/css"> </head> <body> <p id="console"/> <div id="ourItem" /> </body> </html>

Modify the file to allow rapid iterations and web updates by addressing the implementation files on a server.

<html><head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Banner</title> <script src="jquery-1.5.min.js"></script> <script src="network_detection.js"></script> <script src="http://<yourserver>/basic_store1.js"></script> <link rel="stylesheet" href="offline.css" type="text/css"> <link rel="stylesheet" href="http://<yourserver>/styles.css" type="text/css"> </head> <body> <p id="console"/> <div id="ourItem" /> </body></html>

Templates

Adobe's Digital Publishing Suite Customer Enablement team has created template implementations of storefronts that can be leveraged as turnkey implementations, or as a bootstrap to your own custom storefront. These all implement a grid layout of folios with various extra modules added as examples.

An archive of these implementations can be found in the Custom_store_templates.zip file.

Marketing

The Marketing template provides a Grid view of folios and a rotating banner area at the top.

Figure 4: Marketing template
Figure 4: Marketing template

Subscribe

The Subscribe template provides a Grid view with a transient subscription image. Once subscribed, this image disappears.

Figure 5: Subscribe template
Figure 5: Subscribe template

Rotating banner

The rotating banner template provides a Grid view with a rotating promotional area above that contains a featured folio.

Figure 6: Rotating Banner template
Figure 6: Rotating Banner template

Twitter feed

It is important to realize that these storefront templates are simply HTML5+JavaScript+CSS3. You can add anything, even a Twitter feed.

Figure 7: Twitter template
Figure 7: Twitter template

Where to go from here

Read the "Merchandising with Adobe Digital Publishing Suite" white paper for more information about how to drive additional revenue through a Custom Store.

Creative Commons Attribution-Noncommercial-Share Alike 3.0 Unported License+Adobe Commercial Rights

This work is licensed under a Creative Commons Attribution-Noncommercial-Share Alike 3.0 Unported License. Permissions beyond the scope of this license, pertaining to the examples of code included within this work are available at Adobe.

Products

  • Acrobat
  • Creative Cloud
  • Creative Suite
  • Digital Marketing Suite
  • Digital Publishing Suite
  • Elements
  • Mobile Apps
  • Photoshop
  • Touch Apps
  • Student and Teacher Editions

Solutions

  • Digital marketing
  • Digital media
  • Web Experience Management

Industries

  • Education
  • Financial services
  • Government

Help

  • Product help centers
  • Orders and returns
  • Downloading and installing
  • My Adobe

Learning

  • Adobe Developer Connection
  • Adobe TV
  • Training and certification
  • Forums
  • Design Center

Ways to buy

  • For personal and home office
  • For students, educators, and staff
  • For small and medium businesses
  • For businesses, schools, and government
  • Special offers

Downloads

  • Adobe Reader
  • Adobe Flash Player
  • Adobe AIR
  • Adobe Shockwave Player

Company

  • News room
  • Partner programs
  • Corporate social responsibility
  • Career opportunities
  • Investor Relations
  • Events
  • Legal
  • Security
  • Contact Adobe
Choose your region United States (Change)
Choose your region Close

North America

Europe, Middle East and Africa

Asia Pacific

  • Canada - English
  • Canada - Français
  • Latinoamérica
  • México
  • United States

South America

  • Brasil
  • Africa - English
  • Österreich - Deutsch
  • Belgium - English
  • Belgique - Français
  • België - Nederlands
  • България
  • Hrvatska
  • Česká republika
  • Danmark
  • Eastern Europe - English
  • Eesti
  • Suomi
  • France
  • Deutschland
  • Magyarország
  • Ireland
  • Israel - English
  • ישראל - עברית
  • Italia
  • Latvija
  • Lietuva
  • Luxembourg - Deutsch
  • Luxembourg - English
  • Luxembourg - Français
  • الشرق الأوسط وشمال أفريقيا - اللغة العربية
  • Middle East and North Africa - English
  • Moyen-Orient et Afrique du Nord - Français
  • Nederland
  • Norge
  • Polska
  • Portugal
  • România
  • Россия
  • Srbija
  • Slovensko
  • Slovenija
  • España
  • Sverige
  • Schweiz - Deutsch
  • Suisse - Français
  • Svizzera - Italiano
  • Türkiye
  • Україна
  • United Kingdom
  • Australia
  • 中国
  • 中國香港特別行政區
  • Hong Kong S.A.R. of China
  • India - English
  • 日本
  • 한국
  • New Zealand
  • 台灣

Southeast Asia

  • Includes Indonesia, Malaysia, Philippines, Singapore, Thailand, and Vietnam - English

Copyright © 2012 Adobe Systems Incorporated. All rights reserved.

Terms of Use | Privacy Policy and Cookies (Updated)

Ad Choices

Reviewed by TRUSTe: site privacy statement