Product Pricing in a Zero Marginal Cost Distribution Environment

Jarrod Drysdale on digital product pricing:

Our strategies were very different. Sacha wrote a book and priced it relative to the cost of other books, which is the strategy just about everyone follows. Instead of that, I wrote a book and priced it based on the value it provides.

Choosing a pricing strategy based on competition is a natural approach, but also a flawed one. Price competition implies scarcity—supply and demand market forces. There is no scarcity for ebooks because digital files are replicated practically for free.

Seth Godin has mentioned this before: there seems to be a ‘race to the bottom’ effect with a lot of eBooks, but many are doing fairly well with pricing way above the competition if they are in a market with scarce competition. Of course this is nothing new – small supply relative to demand results in a above market price.

If you not planning on growing a business or establishing a brand (including your own ‘personal brand’ – your value in the marketplace) then selling a one-off book (or any sort of digital content) by estimating the intersection of supply and demand curves might work.

However, every product has some of auxiliary asset whose value is increased or decreased depending on a product is priced, designed and released.

Mailing list growth. Establishment of a respected voice in a niche market or field. Growth of enthusiastic fans. Possibility of a future acquisition.

All of these intangible assets are not easily valued because in most cases they are dependent on the future. However, they have a real value and possible growth in any of these assets can effect the short term pricing of a product or service. I think this is what makes digital good pricing challenging – why some books are on sale for $3.99, some free, and some less that 150 pages and $50. I don’t think there is ever going to be any one model that works – when you can slice and dice pricing into many different facets the possibilities are endless.

PHP, MS SQL, and Linux

Note: this was a draft from 2009. I never finished documenting everything, and I (thankfully!) no longer have to integrate with the MS SQL database mentioned here. However, I figured I throw this information out there in case someone was running into the same configuration issues I was.

Usually I am lucky enough that most of my clients don’t have many of their internal operations tied into their web site’s databases; if they are using MS SQL or some other database engine that isn’t open source I’m able to easily convince them to transfer their data over to MySQL. Recently I was working with a client where this wasn’t the case, there was no way around it: I would have to integrate with a MS SQL database.

Information on connecting to MS SQL from PHP exists on the web, but most of it is either unclear, incomplete, or outdated. I hope to bundle together most of the information I found into one blog post to make it a bit simpler to compile a custom PHP installation with MS SQL capabilities using the freetds library.

In the PHP installation script I changed/added the freetds installation line to this:

SYBASE={$INSTALLDIR}
LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:$SYBASE/lib
export SYBASE LD_LIBRARY_PATH

cd ${SRCDIR}/${FREETDS}
./configure --prefix=${INSTALLDIR} --with-tdsver=8.0 --enable--msdblib --enable-sybase-compat
make
make install

References:

MacRuby, CocoaPods, 10.7, and XCode 4.3

I have a MacRuby project that uses CocoaPods for many of its ObjC dependencies. I had a bit of trouble getting it to run properly with the latest version of Xcode (4.3). This had to do with a recent change I made to MABSupportFolder (use of isEmpty()) which triggered a fairly obscure bug in addition to the new XCode 4.3 organizational structure not being properly recognized at first.

The obscure MacRuby bug was being caused by running -count on an NSString. When using MacRuby if you test if a NSString responds to -count using -respondsToSelector: you’ll get true as the response because of Ruby’s String#count method. However, that method requires an argument, but running respondsToSelector:@selector(count) will return true for an NSString. This bug was triggered because of my usage of Will Shipley’s isEmpty() function.

If you recently upgraded to Xcode 4.3, make sure you run this command (got this tip from here):

sudo xcode-select -switch /Applications/Xcode.app/Contents/Developer

Or `pod install` will not run properly. Also, I just found out that CocoaPods does not use macruby anymore – you can run it using the system ruby install.

For someone trying to get MacRuby working with CocoaPods here is my Podfile:

platform :osx

dependency 'FMDB'
dependency 'ASIHTTPRequest'
dependency 'MABToolkit'
dependency 'KFAppleScriptHandlerAdditions'

# Enable garbage collection support, which MacRuby requires.
post_install do |installer|
installer.project.targets.each do |target|
target.buildConfigurations.each do |config|
config.buildSettings['GCC_ENABLE_OBJC_GC'] = 'supported'
end
end
end

generate_bridge_support!

The top of your main.rb should look like this:

framework 'Cocoa'

load_bridge_support_file NSBundle.mainBundle.pathForResource("Pods", ofType:"bridgesupport")

Create Gzipped Tar Archive Service for OS X 10.6 + 10.7

Although the tgz command line syntax is very simplistic, I’ve never managed to remember the exact flags for the command line interface. Additionally, if I’m clicking around in the Finder I don’t want to have to fall back to the command line to create a tgz archive. Inspired by this hint you can download a service to create a tgz archive that works with Snow Leopard and Lion.

Scripting OmniGraffle: MySQL Visualization & JSON Representations

OmniGraffle is a great tool for visually mapping out complex relationships or hierarchical structures. Often when working in groups where some of the personnel have no programming or mathematical background OmniGraffle is a great tool to bridge the gap.

Converting OmniGraffle Hierarchy to JSON

Often I’ll use OmniGraffle to map out site structures with non-programmers. The challenge is once everything has been done in OmniGraffle it is normally a manual process to convert the data in OmniGraffle to a structured data representation, like JSON, that is easy to programmatically work with. Or, in my specific case, output the structured OmniGraffle document into a text document that could be reviewed and edited by others on a Google Doc. I wrote a script to pull structured data out of an OmniGraffle document.

Visual MySQL Database Structure in OmniGraffle

Pretty cool tool to visual a MySQL database in OmniGraffle (including foreign keys!). I did not write the original version, but I modified it to work with the latest version of OmniGraffle. Check out the modified MySQL to OmniGraffle visualizer.

JPEG + PNG Color Management Strategies for the Web

The first step in the design process of any website is to mockup the design in Photoshop. One of the most frustrating parts of the design process can be converting your mockup into image slices whose colors mix well with native CSS styles. Mark Edwards, over at Bjango, has a great writeup on color profile management and UI design. The basic tenants are: don’t color manage, use native monitor color profile, use RGB, and do not attach color profiles to JPG or PNG images.

However, in my senario, I often work with graphics that have been designed by people who work in print and don’t understand web image generation in the slightest. Often I’ll receive unoptimized PNGs, JPGs in CMYK, images with color profiles, etc. This can cause image display issues in IE, color shifting, and generally hurt the performance of a website.

In order to help myself optimize images for the web I created a small tool with an associated BASH script to convert CYMK images to RGB, strip color profiles, and optimize image file size.

This tool arose from noticing that Preview.app seems to optimize file size pretty well for PNG and JPEG. I tried to mimick the Preview.app export and while looking through the NSImage APIs noticed you could pretty easily strip color profiles and convert CMYK to RGB.