Prerequisite knowledge
  • Working knowledge of creating folios with Digital Publishing Suite and using Viewer Builder to create a custom viewer application for the iPad
  • Knowledge of HTML and JavaScript
  • Your own public/free folios pre-published to a DPS account
User level: All
Required products
Additional required other products (third-party/labs/open source)
Sample files
By downloading software from the Adobe Web site you agree to the terms of our license agreement. Please read it before downloading.


Note: If you have questions about this article, use the DPS forum. Please don’t contact technical support with questions about Adobe Developer Connection articles.


This tutorial focuses on the basics of Storefront customization for Adobe Digital Publishing Suite (DPS). After completing this tutorial, you will have an understanding about how custom storefronts work, how they can be developed, and how they can be integrated into Adobe DPS Viewer applications. Storefronts are developed using HTML(5) and JavaScript. In this tutorial, you'll use the iOS platform for deployment, but the same methodology applies to Android environments as well. With good development practices, the storefronts can be developed for cross-platform usage.

Getting started

Standard DPS comes with a default library in which the user can buy, download, and view publications that are available. This library is not customizable and has minimal capabilities to incorporate marketing messages. Using storefront customization, publishers can differentiate themselves, extend their brand identities, and incorporate marketing activities into their apps.
Samples of current applications with custom storefronts on iOS that can be found in the iTunes app store:
In this tutorial, you'll use the following resources:

Basic custom store APIs

Each application within Adobe DPS Enterprise Edition can be extended via the JavaScript Viewer (Custom Storefront) API. This will give developers the opportunity to design and develop their own storefronts and make calls into the viewer for common viewer actions.
The DPS viewer application extends the WebKit framework and adds the additional calls listed in the API. The API documentation explains the available API calls and provides small examples.
API highlights
The following is a basic overview of the important APIs:
  • getFolioData: This is one of the first calls that the store will make to retrieve the list of folios that are available in the application. The data is returned as a JSON object.
  • viewFolio: This API instructs the viewer to download a specified folio when it is not available on the device, or open the folio if it was already downloaded.
  • getPreviewImage: The viewer application automatically generates preview images for the covers. To get the URL of these preview images, you can use the getPreviewImage() call. The result will be a JSON object with the status ("result") and the "path" to the preview on the local device.
  • archiveFolio: This API archives the specified folio.
Limitation on callback handling
The current implementation of the viewer only supports one callback function at a time. This means that you'll have to wait for one callback to be complete before you call another function.

Building an HTML custom store

Now that you've learned the basic API calls, this section will focus on building an actual store. This will be done in several exercises. Each exercise has a _start and _finish file. The _start file contains the beginning state for the exercise, in which you can make the modifications. The _finish file contains the end state for that particular exercise. For most of the exercises, the JQuery framework will be used in the examples. Any JavaScript framework can be used to implement the custom stores.
Exercise 1: getFolioData
  1. Open the file exercise_1_start.html in your editor of choice. Have a look at the following items:
  • The DPS JavaScript APIs are included by default on the device. No <javascript include> is necessary to use the JavaScript bridge. But while testing and developing on the desktop, a sample implementation will be used that simulates the behavior of the device. This library is included on line 7. Make sure that this line is removed (or that the js-file is not copied) when you test this later on a device.
  • When running on a device, there is a small delay between starting the app and the availability of the custom store APIs. The viewer will call the callback function that is assigned to window.onadobedpscontextloaded when the APIs are available. Only then may the actual store construction work start. In this case, the init() function is called. When the store is tested on the desktop (testondesktop="true"), this check is being bypassed. Make sure to set testondesktop="false" when you deploy on the device.
  • getFolioData() is an asynchronous call like almost every storeAPI call, and wants a callback function as an argument (line 12).
  1. Uncomment line 12. Open the HTML file in your browser (Safari, preferably) to test the result. A popup should be shown, as seen in Figure 1.
Pop-up message that you should see when opening the finished Exercise 1 HTML file in your desktop browser.
Figure 1. Pop-up message that you should see when opening the finished Exercise 1 HTML file in your desktop browser.
Exercise 2: Show titles for folios
To show titles for folios:
  1. Open the file exercise_2_start.html in your editor of choice. The function showFolios is called to show an initial list of folios.
  2. Extend the code from line 21 to show the title of the folio and the productId. A list of folios should appear. A sample implementation can be found in exercise_2_final.html. The following lines are added in the _final version of the file:
// MODIFY HERE $('#folios').append(folio.title); $('#folios').append(" / "); $('#folios').append(folio.productId); $('#folios').append(" <BR> "); From this exercise on, the JQuery framework is being used.
Exercise 3: Enable viewFolio links
Now that the code generates a list of folios, the links to download or view a Folio need to be added.
  1. Open exercise_3_start.html. The logic to show an individual folio is in the addFolio function.
  2. On line 39 add the following code: {; });
The final code can be found in exercise_3_final.html.
Exercise 4: Folio preview images
The store now renders a list of folios. The next step is to add a preview image for each folio. Preview images can be obtained through a separate call to It takes five arguments, of which two (width and height) are currently ignored. The first argument is the productId of the folio for which the image is requested. The second argument is the orientation; the Boolean value will indicate if a portrait image is requested. The last argument is the callback function that will be called when the image is available.Open file exercise_4_start.html and extend the code on line 73 with the following:
imgElement = $('<img>'); imgElement.attr('class','withStyle'); imgElement.attr('width',120);, false, 0, 0, function(data) {     var result = data && data.result;     if(result == "succeeded") {             imgElement.attr('src',data.path);         } else {             console.log("An error occurred");         } });   folioElement.append(imgElement);
Preview images should now appear for each folio.
Exercise 5: Put the store logic on a remote server
Up until now, the logic for the store has been implemented directly in the HTML page. This page will end up in the ZIP file, which in turn will be baked into the viewer. This means that for any updates to the custom storefront, the viewer must be updated, which can be a complicated and time-consuming process. An alternative is to "externalize" the store. The store logic will be stored on a remote web server and invoked when the store is started.
  1. Open the file exercise_5_start.html.
  2. Create a new file named store.js and move the store logic into it.
  3. Put the store.js file on a web server that is accessible from the web browser.
  4. Include the reference to the script in the HTML file, for example:
<script type="text/javascript" src="http://yourservername[:port] /exercise_5/store.js"></script>
Exercise 6: Network detection
Now that the store has been externalized, proper logic is needed to check if the viewer is online or offline and provide proper feedback to the user. In this case, a separate JavaScript file is used (network_detection.js). This JavaScript file will be included in the viewer. The init() function will be called when the JavaScript Bridge in the viewer is ready, or directly after loading in a desktop situation.Using a jQuery Ajax call, a remote web server will be called using the HEAD HTTP call. If this call succeeds, the viewer is online. If the call fails, the viewer is offline and a message will be shown accordingly. The HEAD call is used to avoid unnecessary network traffic. If the GET method were used, the actual page would be downloaded and directly discarded after receiving it.
  1. Open exercise_6_start.html.
  2. Add the following code on line 9:
<script type="text/javascript"         src="exercise_6/network_detection.js"></script>
  1. Add the "#offline" div to the HTML body on line 16:
<div id="offline"> Trying to connect to online store... </div>
Exercise 7: Deploying the store in Viewer Builder
Now that the store is working, it will be packaged for deployment in Viewer Builder, and you will create the actual viewer.
  1. Modify exercise_7.html on line 10 to add the address of your web server where the store.js file is saved.
  2. Select the following the HTML/JavaScript files to be packaged into one ZIP file: exercise_7.html, the jquery folder and the exercise_7 folder with network_detection.js in it. See as an example. There should be one HTML file on the root level of the ZIP file. All other files are included in subfolders.
  3. Open Viewer Builder.
  4. Create a new Viewer with type "Multi-Issue." Complete the fields as appropriate for your own folios (see Figure 2).
Viewer Builder, creating a new Multi-folio Viewer
Figure 2. Viewer Builder, creating a new Multi-folio Viewer
  1. In the Title ID field, provide the AdobeID for the account that holds your folios that you want to display in the Custom store. This account should have been set up before as an Application Account in the DPS Account Administration Tool.
  2. In the Password field, provide the password for the Application Account.
Walk through the various screens in the process. First, you'll add icons and splash screens in that section (see Figure 3); then, in the Navigation Toolbar section, the store will be added to the actual viewer (see Figure 4). In this case, only assets for iPad and iPad2 will be used (no Hi Res assets for the new iPad).
Viewer Builder: Specifying icons and splash screens
Figure 3. Viewer Builder: Specifying icons and splash screens
Viewer Builder: Adding the store to the navigation toolbar .
Figure 4. Viewer Builder: Adding the store to the navigation toolbar .
  1. In the lower half of the screen, click the + sign below the black horizontal bar. This will add a new custom slot to the navigation toolbar.
  2. Select the newly created slot.
  3. Provide the icons for the slot (Up, Down and Disabled). Sample icons are found in the View Builder—Icons folder.
  4. In the Type field, select "WebView".
  5. In the Label field below type "Store".
  6. In the field "HTML Resources ZIP", select the ZIP file you created earlier in Exercise 7.
  • Make sure testondesktop=false is set in the store.js file.
  • You might want to repeat the last section to add a second custom button and add the store_explorer/ as well (see Figure 5). This is a useful "Store API Explorer" page that will let you test the store APIs from within your app.
 Viewer Builder: Adding the Store API Explorer to the navigation toolbar.
Figure 5. Viewer Builder: Adding the Store API Explorer to the navigation toolbar.
  1. Complete the viewer creation process and wait for the viewer build to be completed on the build server.
  2. After the viewer is created, download the viewer and install the developer version on the iPad.
  3. Test the custom store on the iPad; make sure the iPad is connected to the Internet to be able to view the custom store.

Store API Explorer

The provided Store API Explorer (in can be added to your viewer in a slot in the navigation toolbar. The Store API Explorer can be useful during the development of a custom store—it enables you to execute functions directly in your existing folios for testing and debugging (see Figure 6).
Store API Explorer, running in a Viewer application from a custom toolbar icon.
Figure 6. Store API Explorer, running in a Viewer application from a custom toolbar icon.
The getFolioData() call retrieves an array of folio descriptors known to the Viewer's library. Valid folioState values are as follows:
Value identifier
Numeric value
The folio is not yet available for purchase
Can be purchased and downloaded
There is an active or paused Purchase Transaction for the folio
The folio is free, or its Purchase Transaction completed successfully
There is an active or paused Download Transaction for the folio
The folio content is stored locally.
There is an active or pause Extraction Transaction for the folio
The folio is can be loaded in the viewer
The folio is viewable but can be updated
There is an active update download for this folio
The folio is viewable but has an update that can be installed
There is an active update extraction for this folio

Folio states reference

For example, you can test some of the APIs as follows:
  • getFolioData: Scroll down and tap on the "getFolioData" link. This will retrieve the list of folios that are available in the application. See "Folio States Reference" for valid folioState values.
  • viewFolio: Copy the productId of a folio that has status "200". Paste (or type) the productId into the textbox after "viewFolio". Tap on "viewFolio"
  • getPreviewImage: Scroll all the way down to "getPreviewImage" and paste the productId into the first textbox. Enter "0" into the "width" and "height" textboxes. In the current implementation, these values are ignored. Tap on the link for "getPreviewImage". The result will be a JSON object with the status ("result") and the "path" to the preview on the local device.
  • archiveFolio: Paste the productId into the textbox after "archiveFolio" and tap the link. This will archive the folio.

Where to go from here

This tutorial demonstrated the process of developing a custom store. In this example, only free folios were used. When folios are available for purchase, use the call to buyFolio() to initiate the purchasing process. In the same way, subscription purchasing can be initiated.
To get more information about current subscriptions and past purchases, the getReceiptData() call can be used to retrieve that information from the viewer.
A good understanding of the various JavaScript viewer APIs will result in good implementations of custom store fronts.
See the article Build a horizontal swipe storefront with folio preview for a complete template for a custom store that enables users to swipe horizontally through store pages, view folio previews, and navigate to different sections of the store which can feature different categories of product offerings.