Skip to content

Cordova CLI

My Book Marketing Process

bazaar photo
Photo by -Marlith-

Last year, I wrote a technical book, focused on a niche tool of a niche technology. I posted about my writing process, but wanted to write about my marketing process as well. As my father, who has published a few books, says: “once you finish the book, the hard work [marketing] begins”.  After all, the world, and even the Internet, is a big place, and no one was going to beat a path to my door (or yours).

I tried several different marketing channels. Here’s a list and some commentary on how each channel worked in terms of traffic and sales.  My main goal was to drive traffic to my leanpub book page, where purchase was only a click away.

  • I published a blog post about the book and put an embedded ‘buy now’ link on my blog sidebar. I also did some follow up posts about Cordova CLI, including one about accessing more info from hooks in later version of Cordova and running multiple version of Cordova. Hard to tell if the additional content helped, but I had quite a few sales referred from my domain.
  • I set up a Google alert for ‘cordova CLI’ to see if there was anyplace I could reply and help people with questions while linking to my book page.
  • Monitored and answered Stackoverflow questions about Cordova and Cordova CLI–these typically also figured prominently in the Google alert. SO was the third highest referrer to my leanpub book page.
  • Google adwords: this didn’t work so well. I had 7K impressions and a 0.52% CTR but no conversions. I ran the campaign for about two months, but most of the keywords were pretty obscure.
  • Guest posts at on topic blogs: this worked great. I posted two different posts–Three hooks your Cordova/Phonegap application needs and Phonegap makes mobile app development more accessible. The more aligned the blog post was with the audience of the blog, the better the conversion. I also engaged in the comments section as well.
  • Emails to tech influencers (often with a coupon for a free or reduced price book). This was both marketing and a ‘thank you’ to all the people who either help out with Cordova, or who I have read for years and just wanted to thank (ahem, Matt Raible). It did result in some tweets. Thanks to Jason Grigsby, Brian Leroux and Holly Schinsky
  • Posting on the phonegap google group about the book, with a coupon. This didn’t drive that many visits, but the ones who did converted very well (>25%).
  • Posting on the phonegap google group answering general questions with a link in my signature. This drove some traffic and lead to one conversion. It didn’t scale very well, as when I stopped answering questions, the traffic fell to zero quickly.
  • Emails to members of the phonegap developer directory. I ended up sending out about 50 of these (both myself and hiring someone from Odesk). Surprisingly, I didn’t see any sales from these emails, which were admittedly “cold calls”.
  • Posted to hackernews. No discussion, but a non trivial number of visits.

Here are some things I should have done, or should have done sooner:

  • Set up a custom domain, like this person did.
  • Build a useful email list.  I actually have one, but it’s hard to find out how to subscribe.  Oh, and post to said list.
  • Written and flogged a talk about Cordova. There are probably two or three meetups in the Denver or Boulder area that would have been happy to have me talk, and I expect I would have sold some books through that venue.
  • Added the book to Amazon and Barnes and Noble. I just did that (links to Amazon, Barnes & Noble). Leanpub makes it silly simple to do this, however the royalty hit you take for the distribution is high.
  • Written more articles and pitched them to online magazines. In fact, I should have, when writing the book, queued up 3-5 articles to pitch to publish on launch day.
  • Emailed my readers via leanpub and asked how I could help them (I did this, belatedly).
  • Kept the book up to date. (I still may review, expand and update the book, because it is still a topic that interests me (and there is interesting stuff happening with Cordova, like Ionic and Google Glass support.)

I missed some of these marketing opportunities because my life just got too busy. Others because we stopped using Cordova at my day job, which meant I had less interest in keeping up with Cordova in general. And that, in turn, made it hard to keep up with marketing effort.

The final piece of advice I would share about marketing an ebook is that it is a long game. I realized that even a book on a topic so short lived as a Cordova book–it covers 2.9, 3.0 and 3.1, and the current version is 3.5–there are still ‘long tail’ effects. I make sales now, almost a year after first release.

My Book Writing Process

writing photo
Photo by mrsdkrebs

I wrote an ebook last fall. It’s about the Cordova command line tool (Cordova CLI). Cordova is a way for web developers to build mobile apps that are distributed via the various app stores and can access app fucntionality (your list of contacts, for instance). The CLI is the main method of interacting with Cordova–managing your files, building apps, etc. It’s a niche, but one that I felt passionately about. I love the command line and I love webapps. I find the whole native app experience distasteful. (“Didn’t we already watch this movie?”)

I thought I’d share some lessons from this experience. This post will be about the writing, the next one about the marketing, and the final one about the results.

I wrote a series of blog posts, gathered here, to determine if I would enjoy writing a book, and to give me a head start on the content. Those blog posts were primarily written in July when my wife was away visiting family. I figured that if I didn’t want to write the book, the blog posts would have value anyway–writing clarifies issues for me. If they were useful and shared, then I would have some market validation.

On August 1, weeks after publishing my first Cordova blog post, I received an email from a reader who said the posts were useful, and asked a question. This was enough validation that I decided to start the book. It was five weeks from creating the project on leanpub to completing it (late August to early October).

During the book writing, I focused on expanding on the blog posts to make sure they were authoritative, adding new content as I came up with questions, and verifying all the claims using the Cordova software. I remember spending an hour trying to confirm one part of one sentence in the book. I also spent time answering and asking questions on the Cordova/Phonegap Google group. I also monitored the Cordova developer list, more for interesting topics than for dialog. And a new version of Cordova (3.1) was released just a week or so before I was done with the book, so I spent some time double checking how the new version of the CLI worked.

As far as time, I averaged an hour a day for that five week period–remember, a good chunk of the content was already written and I was simply revising it. I found time on the weekends and in the early morning.

I ended up finding a flickr image to use for the cover page–thanks Marc!

In the end, the writing was fun and a grind all at the same time. You just have to make the time.

Accessing more build information from your Cordova CLI hooks

Hooks now give you, as of cordova CLI 3.3.1-0.4.2, much more information about the environment you were executing in.

Before, if I had platform specific code, I needed to check at runtime:

App.config.flurryid = "";
    if (window.device && window.device.platform) {
        if (window.device.platform == "Android") {
            App.config.flurryid = /*REP*/ 'notreallyanandroidflurryid' /*REP*/ ;
        }
        if (window.device.platform == "iOS") {
            App.config.flurryid = /*REP*/ 'notreallyaniosflurryidxxx' /*REP*/ ;
        }
    }

Now, you can inject platform specific code at build time, via hooks. The runtime code is simplified to

App.config.flurryid = /*REP*/ 'myflurryid' /*REP*/;

and you just replace 'myflurryid' with the appropriate value from your configuration file (more on platform specific configuration files).

From the readme in the hooks directory:

All scripts are run from the project’s root directory and have the root directory passes as the first argument. All other options are passed to the script using environment variables:

* CORDOVA_VERSION – The version of the Cordova-CLI.
* CORDOVA_PLATFORMS – Comma separated list of platforms that the command applies to (e.g.: android, ios).
* CORDOVA_PLUGINS – Comma separated list of plugin IDs that the command applies to (e.g.: org.apache.cordova.file, org.apache.cordova.file-transfer)
* CORDOVA_HOOK – Path to the hook that is being executed.
* CORDOVA_CMDLINE – The exact command-line arguments passed to cordova (e.g.: cordova run ios –emulate)

Here’s a sample plugin which you can put in your hooks/before_prepare directory. If you do this and then run cordova -d prepare you can see the values for all the variables.

#!/usr/bin/env node

console.log("process.env.CORDOVA_VERSION: "+process.env.CORDOVA_VERSION);
console.log("process.env.CORDOVA_PLATFORMS: "+process.env.CORDOVA_PLATFORMS);
console.log("process.env.CORDOVA_PLUGINS: "+process.env.CORDOVA_PLUGINS);
console.log("process.env.CORDOVA_HOOK: "+process.env.CORDOVA_HOOK);
console.log("process.env.CORDOVA_CMDLINE: "+process.env.CORDOVA_CMDLINE);

Here’s the output for a test project.

Executing hook 

""/home/mooreds/git/testproject3/hooks/before_prepare/test.js" 

"/home/mooreds/git/testproject3""
process.env.CORDOVA_VERSION: 3.3.1-0.4.2
process.env.CORDOVA_PLATFORMS: android
process.env.CORDOVA_PLUGINS: 
process.env.CORDOVA_HOOK: /home/mooreds/git/testproject3/hooks/before_prepare/test.js
process.env.CORDOVA_CMDLINE: node /usr/local/bin/cordova -d prepare

Note that if you are using this for platform specific code, you will want to run the commands separately: cordova build android and cordova build ios. If you just run cordova build and you have both ios and android platforms installed, the process.env.CORDOVA_PLATFORMS variable will be android,ios, and your code won’t be able to differentiate between them.

If you want to know about more Cordova CLI changes, check out “3 Cordova CLI Changes You Should Know About” which covers version 3.3.1-0.3.1.

How to use platform specific configuration in your Cordova app

This post comes out of a question I answered over at the guest post I did on Devgirl’s blog, ‘Three Hooks Your Cordova Project Needs’.

A commenter asked:

How do you retain the project level settings for cordova Android projects? Platforms folder removes project level setting when you run ‘cordova platform rm android’

I answered over there, but thought I’d expand a bit and write a post here.

When you are doing Cordova development, there are two main tooling paradigms. You can use native tooling (Eclipse, XCode) to manage your source, edit your javascript and CSS, etc–this is called ‘Native Platform Dev’. Or you can use tooling more typically used in web development (a text editor like Sublime or vi) plus Cordova CLI–this is called ‘Web Project Dev’. Here’s a bit more on the names of these paradigms.

In the first case, you are probably not removing the files under platform all that often–you are more likely to work out of that directory. In the second case, everything under platform is derived from your www directory, plus your plugins, so you can remove the platform directory easily.

I can’t really speak to Native Platform Dev, because it isn’t a Cordova workflow I’ve used. My book is entirely about Web Project Dev and how to do it most efficiently. If that is your paradigm, I imagine you won’t have much trouble with platform specific settings, because the native tooling is pretty good about capturing that in version control, so you can rely on it.

If, on the other hand, you are using Web Project Dev, then if you want to modify platform specific settings, you have three options:
You need to either:

  1. Only modify your project in ways that can be expressed in config.xml. Review the config.xml reference and the platform guides to figure out if your needed customization can be captured in this way.
  2. Write an after_platform_add hook which copies your changes over from elsewhere in your source tree (if you have a modified .java file for example).
  3. Write a plugin which modifies an XML files (AndroidManifest.xml) to insert your needed project level config, (an IntentFilter, for example), and add that plugin to your project in an an after_platform_add. Note you can only add XML nodes to config files with plugins, you can’t modify attributes or remove nodes.

Which of these is correct for you depends on exactly which platform specific feature you are trying to modify.

Running multiple versions of Cordova 3.x

cordova, the command line interface to the Cordova development framework, is a node package. npm, the node package manager, has the concept of a ‘global’ install and ‘local’ installs. Typical installs of the cordova command line interface instruct you to perform a global installation. That is what the -g in npm install -g cordova (from the docs) means. Installing globally means that one version of cordova is available to every user on that computer, and will be installed in a system directory (for example, /usr/local/lib/node_modules, on linux). If you upgrade that one version, everyone and every project on the system will be upgraded (or forced to upgrade, depending on your perspective).

If you want to run different versions of cordova for different projects, you have to install locally. That means that all the cordova code will be installed in a local directory, rather than a system wide directory.

Why might you want do this? Any number of reasons, but primarily because the relationship between your application and a particular version of Cordova is important.

  • If your application depends on bugs or feature behavior that has changed between versions, you could need to freeze your application at a given version of Cordova, at least until you were able to update your application and test it against a newer version.
  • You could have multiple applications that were developed at different times, and the older ones could crash if upgraded (or perhaps you don’t have the time to test against the latest cordova version).
  • Applications under active development may be at the latest and greatest version of cordova, while the others may be sitting at what was the latest and greatest when they were last modified.
  • A local install will let you test your application against a new version of cordova without committing a global install, which might affect other team members, other projects, or necessitate a downgrade if the new version has issues.
  • You might be working on a platform that is not amenable to being place in a virtual machine (like iOS) and yet still want to run different versions of Cordova on the same machine.

Below, I outline steps to follow if you want to have one project using Cordova 3.3 and another using Cordova 3.1. npm view cordova lets you view the available versions–typically you want the latest minor revision (3.3.1-0.1.2 is better than 3.3.0-0.1.0). These are steps for Android, but it would be similar for any target platforms. And these steps assume you have successfully installed the target platform tools for Android previously.

mkdir cordova3.3 # or cordova3.1
cd cordova3.3 # or cordova3.1
npm install cordova@3.3.1-0.1.2 # or 3.1.0-0.2.0
mkdir project
cd project 
../node_modules/cordova/bin/cordova create test33 io.cordova.HelloWorld33 # or test31 io.cordova.HelloWorld31
cd test33 #(or test31)
../../node_modules/cordova/bin/cordova platform add android
../../node_modules/cordova/bin/cordova plugin add org.apache.cordova.device

Don’t forget to add the device feature to your config.xml

<feature name="Device">
    <param name="android-package" value="org.apache.cordova.device.Device" />
</feature>

You need to update the www/js/index.js file to display your Cordova version. This is only to prove you have different versions of Cordova running on the same machine

onDeviceReady: function() {
        alert(device.cordova);
        //app.receivedEvent('deviceready');
    },

Finally build the application and run it on your emulator:

emulator -avd avdname # start a previously created avd via the android command
../../node_modules/cordova/bin/cordova build android
../../node_modules/cordova/bin/cordova emulate android

Note that there should be no issues with running applications built with different versions of cordova on the same device–the applications are all sandboxed.

If you are often in this situation, you can create aliases that point to the correct version of the cordova command, since the results are indeterminate if you mix and match calls to different versions. For example:

alias cordova31='/path/to/cordova3.1/node_modules/cordova/bin/cordova'
alias cordova33='/path/to/cordova3.3/node_modules/cordova/bin/cordova'

Incidentally, I tried these steps out with the latest version of the android tools (version 19 of the Android build tools) with all four of the latest minor revisions of cordova: 3.0.10, 3.1.0-0.2.0, 3.2.0-0.4.0, and 3.3.1-0.1.2, and could only get the 3.1.x and 3.3.x versions to work. So another reason to do a local install is to perform a quick check to see if your platform installation is compatible with a given version of Cordova.

Do you have different versions of Cordova installed on the same machine?

Guest posts about Cordova CLI

I’ve recently had the good fortune to write a couple of guest posts at some blogs to promote my book about the Cordova CLI.

First, I wrote a post on the CloudFour blog: “PhoneGap makes mobile development more accessible”.

But PhoneGap, a four year old project, now lets developers leverage standard web technologies such as CSS, HTML and JavaScript to build mobile applications. Designers who know CSS and HTML can create fantastic mobile friendly user interfaces (leveraging frameworks like Topcoat and Junior) and developers can focus on functionality and performance.

CloudFour is a consultancy based in Portland OR that my company has worked with in the past. They focus on the mobile web, and are very sharp.

Second, I wrote a post about hooks on Devgirl’s weblog: “Three hooks your Cordova/PhoneGap project needs”.

These hooks automate three common scenarios that will take place in almost any Cordova application–adding plugins to an app, switching between deployment environments, and adding custom icons and splash screens.

Write a hook anytime you have a build process that is tedious, repetitive, or required to build your app. Look carefully at any documented manual build processes. If you need to perform steps to build your app (copying icon files to various directories under platforms, for example), see if you can automate them in a hook script to make your build process quicker, easier, and more repeatable.

Devgirl, aka Holly Schinsky, is a developer evangelist for Adobe who has written about a wide variety of topics, including push notifications and Flex.

Leanpub ebook: Developing Cross Platform Mobile Applications with Cordova CLI

I took the content from my blog posts about Cordova CLI, and am revising and updating it for an ebook about Developing Cross Platform Mobile Applications with Cordova CLI. I discuss some of the intricacies of Cordova CLI in more depth than either in my blog posts or in the Cordova documentation.

If the topic interests you, I’d love to hear your feedback.

Plus this gives me a chance to use Leanpub, which I’ve written about previously.

Cordova CLI: In Conclusion

I hope I have convinced you that when you are planning your next Cordova/Phonegap application, you should use Cordova CLI. While definitely not fully baked, this powerful framework makes it possible to maintain a Cordova application for much longer, and makes building and deploying for testing and development a breeze. Feel free to contact me if you have questions.

Again, remember these posts only cover cordova cli 2.9. Cordova 3.0 is an overhaul that changes how the core Cordova app is assembled, and therefore has different constraints.

In conclusion, here’s a list of all the posts around Cordova CLI:

Subscribe to my infrequent Cordova newsletter

Releasing with Cordova CLI

When you are done developing your mobile application, you will want to release the binary, and have it distributed by whatever means is typical for that platform (typically some kind of app store).

How does Cordova CLI help with this? It doesn’t.

Typically, the best way to release a cordova/phonegap application for a given platform is to find out how to do a release for that platform from the platform’s documentation, and follow that. For instance, for android, you can run ant release and sign an apk with custom keys–all of that process is independent of Cordova CLI.

It’s worth reiterating that cordova CLI is a toolset to help with development of applications–deployment is still platform specific.

Next up, a conclusion.

Subscribe to my infrequent Cordova newsletter