Category: Stranger Studios

Don’t Call Your Customer a Dick

Yesterday Adriaan Pienaar, a.k.a. “Adii Rockstar” of Woo Themes posted on his blog about a tough client asking, Am I being irrational? He later followed up on Twitter, calling this customer a “dick client”.

So glad not have had a repeat of yesterday’s interaction with a specific dick client (http://t.co/P6six9a) today. :)

@adii

adii

Now I’ve definitely had similar conversations among friendly company in private, but I would never post something like this to my blog or Twitter. I feel bad even propagating the story more, but I’ve seen some similarly toned tweets go out by developers and consultants and I want to (1) talk about why this might be a bad idea and (2) find out why most people seem to be okay with these kinds of expressions.

Judging by the comments on the blog and Twitter, the WordPress community has mostly got Adii’s back on this one. However I think in this situation, while Adii has some good points and understandable “beef” with this client, he is being a bit irrational.

The back story.

You should read his blog post for the proper context and to read Adii’s and others’ comments. I’m going to paste what Adii wrote of the exchange here, even though it’s about 90% of the entire post, because it’s short and I want to be clear about what I’m referencing. Adii writes (emphasis mine):

  1. Customer notes to us that he is struggling to achieve something with our product.
  2. We explain that this is currently a limitation, but immediately update & release a new version of the product to help the customer achieve their goal.
  3. Customer isn’t happy, e-mails us for refund.
  4. [This is where I come in.] I ask the client whether the fix worked in an attempt to determine how I can help the customer.
  5. Customer says they didn’t try it and won’t try it, because they don’t want to be a guinea pig. Insists on refund, threatens with chargeback.
  6. I explain that we released a fix for the problem and hence it’s not about being a guinea pig; we’re just doing our job & helping them out.
  7. Customer ignores last e-mail, rudely threatens to publicize this and again threatens to go the way of a chargeback.
  8. I issue refund and at least attempt to explain our actions in this regard & how we actually tried to help. Still awaiting response (if any is going to be forthcoming).

Now, to be fair, Woo Themes has a “no refunds” policy (see below). So Adii is in his right to refuse a refund initially (though he eventually gave one). And I think the client is lame for threatening to do a charge back through his credit card (which would refund the money and add another fee to Woo Theme’s account). However, despite the no refunds policy, Adii does end up giving one and seems open to giving them with justification. It’s clear that Adii doesn’t think “fixing a bug”, as he called it, is a good reason for a refund. And it’s possible Adii only gave the refund to avoid the bad publicity and bad affects of a charge back. Adii writes in the comment how he is frustrated at the power customers wield in these transactions.

Is this customer irrational to want a refund?

I think the customer here wasn’t being irrational (in his refund request at least, though he may have had an irrational tone). It sounds like this customer bought the theme thinking it already had a feature he needed. It didn’t, and although Woo Themes fixed the issue right away, I think it is okay for the customer to not be satisfied with this. The customer expected one thing and got another. Despite the quick fix, the customer has reason to question the robustness of the “fix”, which is grounds for a refund in my book.

10. [Woo Themes] Refund Policy

Since WooThemes is offering non-tangible irrevocable, digital goods we do not issue refunds after the subscription or individual theme purchase is made, which you are responsible for understanding upon registering at our site.

By the way, just because the customer may have some justification for asking for a refund doesn’t change the fact that it sucks to lose a customer and to have possibly done some work on a feature just for them. It sucks.

What are we even talking about?

Adii seems to want to bring up two points for discussion. One is about the power customers wield with the threat of a chargeback. The other related point is about the desirability of unconditional refunds. The points are related because it seems the chargeback threats are effectively forcing Woo Themes to offer unconditional refunds even though they may not want to.

For the record, I think unconditional refunds are a good idea… especially when it comes to GPL software.

For one, the point about digital good being irrevocable (made in the Woo Themes policy) doesn’t hold as much weight when the software could technically be distributed for free elsewhere due to the nature of the license. I think many are trying to offer GPL software for a fee and basically hoping that a free version doesn’t crop up… or using split licenses to try to keep a free version from cropping up. Despite the legality of charging for the software in this way and mantras of pro-GPL folks that it’s “free as in speech, not as in beer”, GPL software WANTS to be free as in beer too. It’s kind of natural. it’s supply and demand. People will want your software for free… and if it’s GPL and distributed there will be those able to redistribute for free.

I don’t think you need to stop charging for software (there are many benefits to getting the software “from the source” which is worth a fee), but you shouldn’t be upset if someone gets your software for free… whether it’s from Bit Torrent, an official flavor variant, or by asking for a refund after downloading the software. I’ve only come around this this opinion recently, but I believe that to do GPL software right, we need to make sure most of the value is in that “other stuff” around the software: support, documentation, packaging, trust.

Anyway, back to unconditional refunds. In my experience (and from what I hear) they cause more good than harm. A few will abuse them, but this should be more than made up for by the increased number of sales you’ll get since customers will feel safer about buying something they haven’t tried out yet. That is the argument.

What I would do have done.

It’s funny that the same day Adii posts about this customer, we have a similar experience with a customer for Paid Memberships Pro (our “premium” WP membership plugin). In our case, the customer thought we integrated with a payment gateway that we don’t integrate with yet and asked for a refund. I made the refund first, and then replied with our unwritten policy that we’ll add integration for any payment gateway a paying member requests… it just may take a moment. In this case, our potential/lost customer says no thanks. And I understand, because the customer expected one thing and got another.

As I said, I’ve only come around to this kind of thinking recently. Over the past two months, our return policy has changed from one requesting a reason and requiring the customer to delete the software and vow to not use it, to just requesting the information we need to process the refund. (BTW, Bed Bath and Beyond is a bricks and mortar store that does no-questions refunds to good success.)

Another part of what people expect out of a “premium” WordPress product is better support. And it’s funny that in these cases good, fast support was mostly ignored. This sucks. Not everyone is going to be a customer.

And that brings up another idea that is floating around this discussion: irritable, bad, (dare I say “dick”) clients should be avoided. (The customer we lost was very nice about everything by the way.)

Avoid bad customers. Just don’t feed the trolls.

I agree with the general idea (promoted recently by one of the 37 Signals guys — Jason?) that you don’t need everyone to be your client, and you should use pricing and marketing to target better customers. I would just add that you shouldn’t air the dirty laundry when you do manage to shrug off a bad client. Calling them out in public (if they’re not under a rock, they’ll know that you’re talking about them) may bring them back for more. It will definitely send a message to potential clients reading the rant that working with you might be difficult.

Maybe you don’t want clients who are afraid of being called a dick. You only want clients that are willing to spend a lot of money and never ask for a refund. Just be careful that you’re not turning off clients you do want. There is a fine line between “keeping it real” and pushing away perspective clients.

In summary…

In summary, I think Adii probably handled things correctly up to the point that he posted about it on his blog and twitter. He was trying to bring up some things that should be discussed, but I think his emotions lead him to post it too quickly and in a way that makes it obvious who he is talking about… and he used that D word there.

He could be scaring away potential customers. (I mean look what Chris Pearson’s attitude towards WordPress did to his credibility in the community. Our attitudes toward our clients are similarly important.)

Adii, and some others in comments/etc, missed the point that the customer paid for something under false pretenses. Whether this is the customer’s fault.. or if in our opinions the customer should have been happy about the quick fix, he or she still has a decent reason to want a refund: it is valid to question whether the “quick fix” will be as robust as the customer expected. Whether or not one should be granted is up to the business and their refund policy.

Customers threatening chargebacks when they aren’t warranted sucks. I feel in general though, it is more important to protect customers by allowing chargebacks than it is to protect businesses from their misuse. We don’t make money by forcing people who don’t want to pay for our products to pay for them. We make money by making the customers that are willing to pay happy.

The digital nature of software works both ways. Someone can get the software and then chargeback to effectively get something for free. But then it didn’t really cost us much to deliver the software either. Especially when working with GPL software, we should be ready to accept situations where people obtain our software for free.

Alright. Let me know what you think. Maybe I’m being irrational here. I don’t mean to pile on Adii. Like I said, I think he did it right up to the point of blogging/tweeting about it. This is all very subtle stuff. We probably agree about more than we disagree, but I don’t think it’s black and white… which is why I wanted to write a million rambling words about it.

Ok, hit publish already, Jason.

 

I’m Speaking at WordCamp Columbus, June 18th at 11:30am

I’m excited to say that I’ve been accepted as a speaker at WordCamp Columbus this coming Saturday. I was a last minute addition… so thanks to the WCC folks for working that out. (Shout out to Angie Meeker: @angiemeeker / blog)

My talk is on “Licensing and Business Models for Premium Plugins”, which is a fancy way of saying “How I plan to make money with Paid Memberships Pro“. Sadly, the event is all sold out, but if you are going or able to squeeze in somehow, I look forward to seeing you there.

More info on the schedule: http://wordcampcolumbus.com/schedule/

Thanks WordCamp Columbus Sponsors: http://wordcampcolumbus.com/sponsors/

Disable the WordPress Admin Bar for Non-Admins Only

Here is a variation of some code I found on Yoast.com to disable the WP admin bar for non-admins only.

function yoast_hide_admin_bar_settings() 
{
?>
	<style type="text/css">
		.show-admin-bar {
			display: none;
		}
	</style>
<?php
}
function yoast_disable_admin_bar() 
{
	if(!current_user_can('administrator'))
	{
		add_filter( 'show_admin_bar', '__return_false' );
		add_action( 'admin_print_scripts-profile.php', 'yoast_hide_admin_bar_settings' );
	}
}
add_action('init', 'yoast_disable_admin_bar', 9);

Just copy and paste this code into your functions.php or another plugin/theme file that can add hooks. Save/upload and watch it work.

Let me know if you have any trouble using this.

Fix for WP Page Tree Plugin in WP 3+

The WP Page Tree plugin is a nice plugin. It shows a tree view of pages in your WP site… but it’s been broken since about version 3 or so.

I’m sure there are other tree view plugins that work well, but I liked that one. And it is actually an easy fix to get it working in WordPress versions 3+.

The issue was that the links generated in the tree view pointed to the old admin URLs for editing pages (page.php?action=edit&post=#). The new more generalized URLs for editing pages is (post.php?post=#&action=edit).

So, what you want to do is find line 404 in wppagetree.php (of version 2.8 of the plugin) and change page.php to post.php. That’s it. The whole block of code around there should look like:

if ($public) {
	// Create our own link to edit page for this ID
	$out .= "<a class=\"$pageStatus\" href=\"$pageURL\">" . $pageTitle . "</a>";
}
else {
	$out .= "<a class=\"$pageStatus\" href=\"" . get_bloginfo('wpurl') . "/wp-admin/post.php?action=edit&post=$pageID\">" . $pageTitle . "</a> <a style=\"font-size: 10px;\" class=\"$pageStatus\" href=\"$pageURL\">#</a>";
}

Or download this zip here which has version 2.8 of the plugin plus that one fix. I may upload it to the WP directory sometime, but then I’d have to maintain. Feel free to do it for me. ;)

Download: page-tree-fixed.zip

WordCamp Philly 2010 Presentation Slides

Here are slides from my talk. I was told a video of the presentation will be up at WordPress.tv sometime soon. I’ll post a link when it is. And I’ll try to get these in SlideShare or something similar. I was having trouble with their site earlier.

Business Models for WordPress Plugin and Theme Distribution
What You Need to Know About the GPL

Download: ppt, pptx

On Ustream: WordPress Plugin to Capture Email Addresses in Exchange For a File Download

Update: No longer streaming. The plugin works great. Kim is going to make it pretty, then I’ll post to WordPress and do a right up.

I’m streaming live right now while I work on a WordPress plugin. Follow me at ustream.tv/channel/stranger-studios.

I’ll be working on a plugin for a feature that we’ve done a million different ways: asking for a user’s email address in exchange for a link to a file download. A solid plugin for this will save us a lot of time. If it turns out well, I’ll put it in the WP plugin directory and link to it from here.

Here are the requirements/specs I have for this plugin:

  • Should use a short code of the form [filedownload: /path/to/file.txt] to define where the form should go and what file.
  • The form will submit to the current page, log the email entered, add a session flag.
  • If an email is in $_POST, the post/page will show the download link instead of the email form.
  • Files will be hidden behind a script to obscure the path to the file. The script will check for the session flag before returning the file.
  • Should use a template to make it easy to change the HTML/CSS for the form.
  • Should be easy to adjust the addEmail code to work with Constant Contact/etc.

That’s it. Please join me. Post questions to the chat. Again, if this code comes out clean, I hope to share it.

Enhanced by Zemanta

WordPress get_the_content_after_more() Function

In WordPress, if you want to get just the excerpt of a post, you can use the built-in functions the_excerpt or get_the_excerpt. And if you want all of the content, you can of course use the the_content or get_the_content functions. But what if you want to get everything BUT the excerpt?

The Code

Here is a function that will do that: get_the_content_after_more()

function get_the_content_after_more()
{
	$content = get_the_content();
	$moretag = preg_match("/\<span id="\&quot;more-[0-9]*\&quot;\">\&lt;\/span\&gt;/", $content, $matches);
	if($moretag)
	{
		$morespan = $matches[0];
		$morespan_pos = strpos($content, $morespan);
		$newcontent = substr($content, $morespan_pos + strlen($morespan), strlen($content) - strlen($morespan));
		$newcontent = apply_filters('the_content', $newcontent);
		return $newcontent;
	}
	else
		return "";
}

How to Use This

Notice that this is a “get_” version of the function. So you will get to echo the results or save them to a variable for future use. Just plop an echo get_the_content_after_more() into your LOOP and you’re good to go.

How it Works

The function works by getting the post content through “get_the_content” (and so will give you the content for the current post in your loop) and looking (preg_match) for the span tag that WordPress puts at the more break. (If older versions of WordPress don’t add this tag, this function won’t work. But this works in 2.9-3.0 at least.)

If a more tag is found, I create a variable $newcontent holding everything after the more tag. Then I run it through apply_filters to all of your plugins/etc that work on the_content will work on this.

If a post doesn’t have an excerpt (no excerpt or more tag in the post), the function returns an empty string.

The function could easily be called get_the_inverse_excerpt or get_the_content_after_excerpt or get_the_content_minus_excerpt. Let me know if you have a better idea for this… or tell me what you searched for to figure this out.

Why Would I Use This?

Kim was updating our portfolio page, which is really a list of WordPress posts. She wanted to style the “excerpt” differently from the rest of the content. Notice how the top section (“WineLog is…”) is in a gradient box on the WineLog portfolio item… and then the rest is styled as written in the post content. We used code like this:

<div class="excerpt">
<?php    
    the_excerpt();
?>
</div>
<?php     	
    echo get_the_content_after_more();			
?>

When we decided to do this, I first checked if WordPress was adding some tag around the excerpt that we could piggy back on. Nope. All that is added is a span like at the point where the more break is. Then I looked for a buit-in function or some parameter of the_content that could be used to do this. No luck. (Let me know if there is a built-in way to do this.)

If I Were Updating WordPress…

… and it’s open source. So maybe I will. One could add a parameter to the_content/get_the_content functions to exclude the excerpt. The code would be largely the same, though they could look for the more tag itself since they won’t have that stripped out yet. That feels clunky to me. Let me know if you have better ideas.

Make One Category Display Full Posts in Thesis Theme

Got a request from a client to have a specific category page on their WordPress blog running the Thesis theme show full posts (vs. excerpts) for just one category. So I’m going to figure it out and write the steps here for the benefit of humanity.

First, to be clear, I’m not talking about changing ALL CATEGORY PAGES from excerpts to full posts. That can be done easily through the Thesis Display Options. You would change the “Posts” display options to “display full content” and the “Archives” display options to “same as home page”.

What I want to do is show excerpts on every category page except one. You do this by settings up a custom category theme, and Thesis has its own way to do that. A custom category theme wasn’t optimal for this install, so I need to do something different. It’s good to have different ways of doing things. Maybe my method below works for you too.

Here’s what we’re going to do.

  1. Use the “thesis_hook_before_post_box” hook to check the current category and if it is the “Quick Takes” category, change the $thesis[‘display’][‘archives’][‘style’] value to “content”.
  2. Use the “thesis_hook_after_post_box” hook to change the $thesis[‘display’][‘archives’][‘style’] value back to what it was before we tweaked it.

Sounds complicated, but it’s only a few lines to add to the /custom/custom_functions.php file in your Thesis theme folder.

function quicktakes_fullpost_setup()
{
	$target_category = "Quick Takes";
 
	//saving the global archives display setting so we can revert later
	global $thesis, $saved_thesis_display_archives_style;
	$saved_thesis_display_archives_style = $thesis['display']['archives']['style'];
 
	//checking the category, if it's the target category, then set the display to full post
	$current_category = single_cat_title("", false);
	if($current_category == $target_category)
		$thesis['display']['archives']['style'] = "content";
 
}
function quicktakes_fullpost_cleanup()
{
	//we're setting the display archives style back to what it was before we tweaked it
	global $thesis, $saved_thesis_display_archives_style;
	$thesis['display']['archives']['style'] = $saved_thesis_display_archives_style;
}
add_action('thesis_hook_before_post_box', 'quicktakes_fullpost_setup');
add_action('thesis_hook_after_post_box', 'quicktakes_fullpost_cleanup');

Be sure to change the $target_category variable to the title of the category you want to change.

If you want to do the inverse of this, which would be to show the excerpt on just one category page and update show the full post on all others, you would:

  1. Change the Thesis Display Options for posts to “display full post content”
  2. Change the Thesis Display Options for archives to “same as your homepage”
  3. Then adjust line 12 in the code above to set the style to “excerpts” instead of “content.

I hope this helps. Let me know if you have any questions about this or similar customizations for Thesis.