More apps for everyone!

September 19, 2012

Updated: MoreApps now uses StoreKit to display the product pages inline in the app instead of opening App Store, as long as you are running on iOS 6 or newer.

Say you have an app that is awesome and gets lots of downloads every day. What if you could easily tell those users that you have a bunch of apps that are equally awesome, and that they should check them out too!

"More Apps" is my attempt at solving this in a hopefully unobtrusive and very pragmatic way. The source is available on github.

Somewhere in the app where it's not too much in the way, I have a button that brings up the "More Apps" view. Here's an example from my training app Intensity:

In this post I'll describe More Apps a little bit more and show where to get it and how to use it.

Features

  • Open source license
  • Works for both iPhone and iPad
  • Can be updated without touching the app by editing the static contents on the server
  • Can be used in a navigation hierarchy or as a modal view
  • Optionally handles the network being down, retries automatically when it goes up
  • Localizable (not to 100% yet but patches are welcome)
  • Uses StoreKit to show the App Store product page inside the app on iOS 6+, opens App Store for iOS 5.

How it works

There is a client side component (for the app), and a server side component. The client side is a simple view that shows the content of the URL you specify, and some logic to handle progress indication and error handling. It also takes care of opening the App Store in a civilized manner (including using the StoreKit provided UI on iOS 6). The server side is a static web page using javascript to dynamically build the page on the client side, filtering a list of app definitions depending on a few parameters provided by the app. The most important filtering done is to remove the app showing the list from the list itself.

While native code is of course preferred in most cases, in this particular case it made a lot of sense to go the other way. You can easily update the More Apps view for all your apps without submitting any updates and waiting for them to pass the review. You can change the rules of what apps are listed in each app, or the entire look of the view, or add translations or special offers and so on.

The current look is based on the original App Store search listings which since have changed dramatically in iOS 6. The good news is you can easily tweak this by editing the CSS yourself if you want another look. If anyone creates other styles, don't hesitate to let me know so I can incorporate them in the repo.

Get the source

I've put the code up on github: MoreApps. There is a demo app included so you can try it out right away.

How to use it in your own apps

You need to include the one class MoreAppsViewController in your code, and add StoreKit.framework to the linked frameworks.

You can also add the included Reachability class, or use your own copy if you already have one. If you do, the view controller will automatically reload once the network becomes available in case an error occurred. If you do choose to use Reachability, make sure to add SystemConfiguration.framework to the linked in frameworks.

[ Note that MoreApps uses ARC (you should too!). If you are not, you need to go in to the build settings, select Build Phases, find MoreAppsViewController.m in the Compile Sources phase, and add "-fobjc-arc" to its compiler flags. ]

Client Side, presenting the view

You only need this snippet:

MoreAppsViewController *controller = [[MoreAppsViewController alloc] init];
controller.appIdentifier = @"DemoApp";
controller.moreAppsURL = [NSURL URLWithString:@"http://mynonexistingwebsite.com/mypromopage.html"];

// Wrap in a navigation controller for the modal case.
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:controller];
[self presentModalViewController:navController animated:YES];

Server side, serving the content

Copy the following files in the DemoData folder to your server:

  • index.html
  • moreapps.css
  • moreapps.js

Create appdefinitions.js and fill it with your app definitions. You do that by setting up one or two variables with JSON structures:

appDefinitions = { ... } // For your list of apps.
affiliateAppDefinitions = { ... } // Optional list with apps from affiliates or friends.

The easiest way to get started is to look at the example version in DemoData/appdefinitions.js and edit it for your own purposes. Here's an example of an app entry:

{ "id": "addidoku", // Identifier, used to filter out "self" from the app list. Just a string.
  "name": "Addidoku", // Either a dict with language/name pairs, or just the name if it's not localized.
  "category": "Games",
  "summary": { // Same as name, either a dict or just the summary.
    "en": "Addictive Casual Puzzler",
    "sv": "Beroendeframkallande pusselspel"
  },
  "link": "http://itunes.apple.com/app/id510574334?mt=8",
  "icon": "addidoku-114.png",
  "type": "free", // Can be free or paid, affects the title of the button when running on iPad.
  "showOnLocales": [], // List of locales, e.g. [ "sv_SE", "nn" ]. Empty list means show on all locales.
  "showOnDevices": [] // List of device types, e.g. [ "iphone", "ipad" ]. Empty list means show on all devices.
}

Icons

The app icons you provide should be 114x114, and the HTML/CSS output will make them look sharp on retina devices, and still have the right size on non-retina devices. The corners are rounded for you so you can just use your regular app icons.

Local testing

You can try things out by just viewing the local index.html on a desktop computer browser, passing various parameters like index.html?locale=sv_SE&device=iphone etc. Possible parameters are:

  • locale, either a full identifier like en_US, or just the language like en.
  • device, can be iphone or ipad.
  • me, the identifier for the app showing the view. Filters out that app from the list.

Those parameters are passed by the app automatically so you don't need to worry about them other than for testing.

Limitations

As you see in the screenshots above, there is no information about the prices. You could improve the code to display the right price and currency depending on the locale but I went with the much simpler solution for now - to not show the price.

Enjoy!