Thursday, January 21, 2010

Anatomy of a Failed PR Stunt

If you're an NFL fan you may already have seen the picture below. This is the story behind the Fire Snyder stadium sign--a self-indulgent PR stunt to promote GridRoom that was reported by dozens of blogs and newspapers but was ultimately a waste of time.

image

For over a decade the Washington Redskins have been run by a comically dysfunctional owner: Daniel Snyder. This in itself is not remarkable. Other sports team owners are regularly mocked for their parsimony, pomposity, and generally psychotic management decisions. Al Davis, George Steinbrenner, Peter Angelos--if you're a sports fan you know the list.

There are two remarkable things about Washington's dysfunction. First, the owner is both young and insane. Not second-generation-wealth young and insane or techno-wiz-kid-billionaire-with-bad-social-skills young and insane, but I-started-a-marketing-outsourcing-company-and-took-it-public young and insane. Who becomes a billionaire at 32 by starting a marketing outsourcing company? Clearly insane and probably unethical. No question about it.

Becoming an insane billionaire at 80, like Raiders' owner Al Davis, is a fairly normal thing. You're a young business phenom. You build your empire. You surround yourself with sycophants, ex-wives, and inheritance-hungry relatives. You become paranoid. You slip into pure crazy. There's a natural progression here that should not be violated. It takes a special man to become an old, crazy billionaire by 35. Daniel Snyder is that man.

The second remarkable thing about the Redskins is that, despite their dysfunction, despite losing more games than 21 other teams over the past decade, they are still the second-most valuable sports franchise in the world ($1.55 billion). They have the largest stadium in the NFL (92,000 seats), charge some of the highest ticket prices, yet have sold every available ticket since 1968, and also have the NFL's longest waiting-list for season tickets (155,000). The Redskins earned $90 million in profit last year, while the median NFL team earned just $26 million.

There are probably other factors contributing to the team's financial success, such as Federal lobbyists' entertainment slush-funds and multitudes of area transplants who support visiting teams, but it's fair to say that Washington has a deeply invested fan base.

This year fans may have reached their breaking point. It started when head coach Jim Zorn was stripped of his play-calling responsibilities, just 6 games into his second season. Snyder has fired and undermined several previous coaches in the same knee-jerk manner, and this time fan anger over the team's losing ways was directed primarily at the owner.

image

Then the team suddenly banned all fan-created signs at the stadium, perhaps worried about the potential embarrassment of anti-Snyder signs at an upcoming nationally-televised game. Predictably, the sign ban was implemented with heavy-handed boorishness. When local media reported that innocuous signs like the one pictured had been seized and tossed into the garbage by stadium security, anti-Snyder furor roared to new heights.

Now, I'm sure you're frantic at this point to hear exactly who was calling plays after Zorn lost the job. Well, that gets complicated. Cerrato hired an outside consultant to call plays for Zorn, but the outside consultant didn't really know much about the team so he only called some of the plays, and he relayed them through other coaches (not Zorn, he could only listen), and the other coaches chimed in occasionally with additional information on certain plays since the consultant didn't really know what he was doing. Zorn claimed he could still call plays during the 2 minute drill. And it was never clear what would happen if Zorn stopped "just listening" and overruled the consultant.

But the exact play-calling flow is beside the point. Something big happened here. Do you see it? Snyder missed a prime revenue opportunity. This is the man whose first mandate as owner was to move training camp back to the Washington area so he could sell tickets--and charge $10 parking fees--for fans to watch practice.

imageOnce you've given up on the season and publicly emasculated your head coach you don't pay someone else to call the plays. You market the play-calling opportunity to your "whales" and let them pay you to call the plays! There are dozens of millionaire football fans who will never crack the exclusive NFL owners club. These folks would pay through the nose to call just one play--let alone all the plays for a drive or quarter. The possibilities are endless: you could have call-till-you score packages; 4th quarter blowout specials; design-and-call combo packages, etc.

This might even improve on-field results. Can you imagine opposing coaches game-planning for the irrational sequences that would result? But Snyder missed this one, and I almost feel bad for him. There's nothing sadder than an over-the-hill maestro, still flailing away before the orchestra when he can't keep up with the music.image

Just as fan anger over the sign ban peaked I wrapped up the last release of GridRoom planned for 2009 and had some free time on my hands. I had an idea for turning the stadium itself into an anti-Snyder sign by having people wear color-coded shirts to form giant letters. I first discarded the idea as a waste of time, and then decided I could justify the effort as a long-shot publicity stunt if I mixed in some GridRoom advertising. Normally something like this would be impossible to coordinate, but it seemed like the perfect confluence of circumstances to give it a try. (Plus all the other anti-Snyder protests in the works were boring and lame.)

To get started I searched for high-resolution photos of the empty stadium, stadium seating charts, and tickets for sale on StubHub and other sites. I even managed to dig up a 10-year old ticket stub from the last game my wife and I attended at FedEx field before moving to Atlanta. With these resources in hand I figured out pretty quickly that each of the upper deck sideline sections forms a near-perfect grid. These rectangular sections would make it easy to test the concept without wasting much time. I whipped up some seating charts, set up the Fire Snyder Sign blog, emailed links to a few friends and bloggers, and posted links on Facebook.

imageThe idea was an immediate hit. It was facebooked, tweeted, emailed, and posted to sports message boards by hundreds of people. It was linked by the Washington Post, ESPN, the Washington Examiner, DeadSpin, the LA Times, and dozens of smaller bloggers and newspapers. In just two weeks the blog was viewed by over 35,000 visitors. It was parodied by eTrueSports, and people even posted ticket ads on Craig's List mentioning the sign. Ticket holders asked how they could help, and some even planned to move into the sign sections to participate. I met Dan Steinberg of the Washington Post when the Redskins and Falcons played in Atlanta, and received interview requests from Bloomberg News. So in one sense the stunt was a moderate success, even though the sign ultimately fizzled.

But the stunt was a complete failure in terms of GridRoom publicity. A $25 Ad-Sense purchase could have replicated the traffic going to GridRoom. If anything this experience drove home how cost-effective Ad-Sense advertising is for advertisers--and how murderous Ad-Sense rates are for content producers. To date, 48,288 page views on the Fire Snyder Sign blog have generated just $17.68 in Ad-Sense revenues!

 

Monday, January 11, 2010

Simple Savant v0.3 Released

I've just released Simple Savant v0.3 at CodePlex. It's been a number of months since the last release so this one includes a number of bug fixes as well as a several significant new features:

  • Typeless operations - All existing functionality has been exposed through methods not tied to .NET item types.
  • Asynchronous operations - All existing operations may now be invoked asynchronously.
  • Default property formatters are exposed for global replacement or reuse.

Each of these features is described in more detail below. See the release notes for a complete list of bug fixes and minor enhancements.

Typeless Operations

Most methods in the original Savant API required a generic type parameter. This made sense since object mappings could only be defined using attributes applied to your .NET types. This also allowed strong-typing of method parameters and return values. Here's an example:

   1: Guid personId = Guid.NewGuid();
   2: PersonItem person = Savant.Get<PersonItem>(personId);
   3: DateTime birthDate = person.BirthDate;

The biggest drawback of this approach is compile-time dependence on the generic parameter, which makes it difficult to invoke Savant methods from tools and infrastructure code that cannot explicitly reference item types in advance.

With Savant v0.3 we can rewrite the code above without referencing the PersonItem type:

   1: Guid personId = Guid.NewGuid();
   2: AttributeMapping itemNameMapping = AttributeMapping.Create("Id", typeof (Guid));
   3: ItemMapping mapping = ItemMapping.Create("Person", itemNameMapping);
   4:  
   5: AttributeMapping dateMapping = AttributeMapping.Create("BirthDate", typeof (DateTime));
   6: mapping.AttributeMappings.Add(dateMapping);
   7:  
   8: string[] propertyNames = mapping.AttributeMappings.Select(a => a.PropertyName).ToArray();
   9: PropertyValues values = Savant.GetAttributes(mapping, personId, propertyNames);
  10: DateTime birthDate = (DateTime)values["BirthDate"];

There is one significant difference between these examples. In the first example we're retrieving all attribute values mapped for the PersonItem type. In the second example we're retrieving only the "BirthDate" attribute. This makes perfect sense since that's the only attribute mapping added to our item mapping.

You may sometimes want to invoke the typeless methods while still working with .NET types. The ItemMapping and PropertyValues classes include helper methods to reduce the code required for this. The example below demonstrates these methods by building a complete mapping from the PersonItem type and then copying the returned values into a new instance of PersonItem:

   1: Guid personId = Guid.NewGuid();
   2: ItemMapping mapping = ItemMapping.Create(typeof(PersonItem));
   3:  
   4: PropertyValues values = Savant.GetAttributes(mapping, personId);
   5:  
   6: PersonItem person = (PersonItem)PropertyValues.CreateItem(typeof(PersonItem), values);
   7: DateTime birthDate = person.BirthDate;

Other benefits of dynamic mappings and typeless operations include the following:

  • Data entity types can be decoupled from the Savant assembly if desired. All the functionality available through Savant mapping attributes can be replicated with dynamically constructed mappings.
  • Data partitioning is now much easier with Savant. To use the same mapping across partitioned domains, simply change ItemMapping.DomainName value before invoking the typeless get, put, or select methods on Savant.

Asynchronous Operations

Any Savant method can now be invoked asynchronously using new extension methods that support lambda expressions. You'll need to import the Coditate.Savant.Async namespace to use these methods. Here's an example:

   1: using Coditate.Savant.Async;
   2: ...
   3: Guid personId = Guid.NewGuid();
   4: AsyncFunction<PersonItem> function = Savant.ExecuteAsync(s => s.Get<PersonItem>(personId));
   5:  
   6: // do something else useful
   7: PersonItem person = function.EndInvoke();
   8: DateTime birthDate = person.BirthDate;

Global Formatter Replacement

Savant has supported custom property formatters since the first release. But these could only be specified for individual properties using mapping attributes. You couldn't, say, replace the formatter used for all DateTime properties without applying a CustomFormatAttribute to every DateTime property defined by your application. Nor could you access the installed formatters for use in other contexts.

Both of these are possible now that the formatter registry is exposed on SavantConfig. Here's how to get and use a default formatter:

   1: PropertyFormatter formatter = Savant.Config.Formatter;
   2: ITypeFormatter dateFormatter = formatter.GetFormatter(typeof (DateTime));
   3: string date = dateFormatter.ToString(DateTime.Now);

And here's how to replace one of the default formatters globally:

   1: PropertyFormatter formatter = Savant.Config.Formatter;
   2: ITypeFormatter dateFormatter = new MyCustomDateFormatter();
   3: formatter.SetFormatter(typeof(DateTime), dateFormatter);
 
Header photo courtesy of: http://www.flickr.com/photos/tmartin/ / CC BY-NC 2.0