Banned from Google AdSense

30 minutes ago, I received this email from Google AdSense:


We continually review all publishers according to our Terms and Conditions and program policies, and we reserve the right to disable publishers or sites that are not in compliance with our policies.

Our specialists have found that your account is not in compliance with these program policies. As a result, we have disabled your account.

Google has certain policies in place that we believe will help ensure the effectiveness of Google ads for our publishers as well as our advertisers. We believe strongly in freedom of expression and therefore
offer broad access to content across the web without censoring results. At the same time, we reserve the right to exercise editorial discretion when it comes to the ads we display in our AdWords program and the sites on which we choose to display them in our AdSense program, as noted in our respective Terms and Conditions.

Thank you for your understanding.


The Google AdSense Team

I immediately filled out an appeal, but I don’t even know why I was banned. The email doesn’t say. Is Google trying to cheat me out of the $570 they owe me? I earned $430 last month and $140 this month I have not yet received, and my AdSense account says they are not going to pay me until “issues” with my account are resolved. WHAT DOES THIS MEAN???

If you use my Tweet This plugin, DO NOT enable “Insert Google AdSense ads to support Tweet This” anymore. Unless my account is restored, Google will just keep the money. It won’t help me at all.

UPDATED 2010-11-11 20:45 GMT: Here are some details of my AdSense usage I posted on this forum:

I’ve been doing the same thing for the past 8 months and receiving Google checks every month, so it’s really surprising that they would ban me now considering I haven’t changed anything!

I display ads on my personal website. I also run a URL shortener called and I display Google AdSense in an iFrame above the redirect page with a link to hide the ads. The service has over 21 million short URLs and makes about $150 per month from AdSense. I got the idea from which does the same thing using Google AdSense ads.

I develop a WordPress plugin called Tweet This which includes the option “Insert Google AdSense ads to support Tweet This.” If checked, this inserts ads with my publisher ID on the plugin user’s blog. Last month, this made $143.

However, I have been doing both of these things for a long time. Tweet This has had the AdSense option since Feb. 2009, and it hasn’t changed a bit. Why would they ban me now?

UPDATED 2010-11-22 05:45 GMT: I have been restored to the Google AdSense program, but I can no longer display ads on other peoples websites. This will reduce my income by 75%, but AdSense still generates more revenue than any other program.

Making WordPress Tag Balancing Work with Exec-PHP

I use the WordPress plugin Exec-PHP to use PHP in my posts, but under normal circumstances if I do this with “WordPress should correct invalidly nested XHTML automatically” (a.k.a. tag balancing) checked in Settings > Writing, I get this nasty error whenever I try to use PHP:

Parse error: syntax error, unexpected ‘?’ in /home/thripp/public_html/wp-content/plugins/exec-php/includes/runtime.php(42) : eval()’d code on line 1

The solution the developer provides is to simply disable that feature. That’s fine most of the time, but I encountered a tricky situation where I needed to use PHP and have WordPress close open HTML tags which I simply could not close.

My posts on this blog are usually photos with short descriptions, but occasionally I write long articles which may go on for thousands of words. Up until last year, my tag, category, and archive pages displayed the full content of my posts. WordPress excerpts were unacceptable for two reasons: 1.) they are always 55 words; 2.) I use Post Thumb Revisited to auto-convert 800×600 images to 400×300 thumbnails, but it only converts them through the_content filter, not the_excerpt. While the excerpt length is customizable in WP 2.8 or newer, I am unwilling to upgrade from WPMU 2.7. What I really needed was an excerpt that used the_content, respected all HTML tags, worked with Exec-PHP, and let me customize the excerpt length.

Enter The Excerpt Reloaded. The plugin was 5 years old, so I found an updated version with bugfixes that was only 3 years old. I quickly wrote this code for my theme’s index.php file and left it this way until today:

if(is_category() || is_archive()) the_excerpt_reloaded(200, ‘all’, ‘content’,
     true, “<strong>… continue reading</strong>”, false, 1, false, false,
     ‘p’, ‘Click to see whole entry.’, true);
else the_content(__(‘… CONTINUE READING’));

This has been the best of both worlds. It cuts off the content at 200 words, so most of my photos do not have a “continue reading” link because my descriptions are under 200 words. Longer posts are cut off after 200 words, so my archive pages do not become unnecessarily long. I had to set the 8th argument of the_excerpt_reloaded, $fix_tags, to false, because I would get the same old Exec-PHP error if it was set to true. “No problem,” I thought. I already have tag balancing disabled in WordPress, so what could it hurt to disable it here?

Recently, however, I encountered an insidious bug when a post was cut at 200 words in the middle of a <strong> tag. The tag would never be closed, meaning the rest of the page would be bold! Take a look at this screenshot:

Unbalanced tags

What do you do about something like this? Obviously, there are many solutions. I could rewrite the offending article so the 201st word is not in the middle of an HTML tag. All I would have to do is put in a few filler words earlier in the article. I could enable tag balancing, write some code to check if each post contains PHP, and not use the_excerpt_reloaded in those cases. I could use custom fields on posts to determine which mode of behavior should be used. I could upgrade WordPress (oh god no). All of these solutions seem suboptimal.

Instead, I went to the problem’s source. If $fix_tags is true, the_excerpt_reloaded runs the content of the excerpt through balanceTags. What is balanceTags? A WordPress function in /wp-includes/formatting.php which activates force_balance_tags. What is force_balance_tags? A WordPress function in the same file which looks like hieroglyphics. All I wanted to do was force the function to ignore PHP, but I couldn’t figure it out. It wasn’t a simple matter of ignoring <?php ?> tags. My PHP tags often appear in the middle of other HTML tags. Here is the source code of a typical photo on my blog:

<img src=”” alt=”<?php the_title(); ?>” />

I took this picture of raindrops falling at night, and my camera’s flash reflected off one of the raindrops. It looks like a star going supernova.

[­sniplet fuji-a360], <?php fexf(); ?>

<a href=”[­sniplet photos-path]stock/<?php echo fprm(); ?>-stock.jpg”>[­sniplet stock-dl-text]</a> (<?php fsze(fprm() . ‘-stock.jpg’); ?>) or <a href=”[­sniplet photos-path]stock/source/<?php echo fprm(); ?>-ss.jpg”>[­sniplet ss-dl-text-lc]</a> (<?php fsze(‘source/’ . fprm() . ‘-ss.jpg’); ?>).

[­sniplet stock-rights]

Looks pretty terrible, huh? I’ve got sniplets in there, custom PHP functions, concatenation, nesting… you name it. This template creates the file paths for the photos, source files, and stock versions right from the post title, because I upload the photos by FTP and follow a rigid file structure. The only reason there’s a full IMG tag at the top of each post is because Post Thumb Revisted won’t create the thumbnails to automatically generate my gallery without it. The template also displays the size of the source files and then extracts and displays the Exif data from the photos in my preferred format, which was extremely difficult to set up and is something I used to do manually. It runs itself, and the functions are really quite interesting.

Anyway, what I needed was a way to bypass force_balance_tags entirely, but only in regard to PHP code. I need the function to close dangling tags like <strong>, <em>, and <u> if the_excerpt_reloaded cuts the post in the middle of a tag.

After a lot of unsuccessful Google searches, I remembered that I solved a similar problem at the beginning of October in Tweet This 1.8. On the “Write Tweet” page, Tweet This uses a modified version of Jeff Roberson’s Linkify URL to delimit URLs with a space on each side (function tt_delimit_urls). A tweet like “Check out!” becomes “Check out !”. Then, I use Ext-Conv-Links by Muhammad Arfeen to convert all long URLs to short URLs if the tweet is over 140 characters (class tt_shorten_urls). This works great for most URLs, but I discovered it breaks URLs containing underscores. gets sent to the URL shortener, which gets converted into, which doesn’t work at all. Totally unacceptable.

After many hours of torment trying to fix Jeff or Muhammad’s code, I decided to approach the problem from a different angle. Why not just replace underscores with something else on the way in, and then change them back to something else on the way out? Good programming doesn’t dance around problems, but I’ll take a practical solution that works over an idealistic solution that fails, any day. But what string to replace underscores with? I can’t use a special character or something that might be used in a tweet on purpose, because it will get converted into an underscore. After some thought, I settled on t9WGb5. It doesn’t look pretty, but it works, and I doubt any URL containing “t9WGb5” is ever going to be purposefully included in a tweet. So I proceeded to write statements like str_replace(‘t9WGb5’, ‘_’, $url) and str_replace(‘_’, ‘t9WGb5’, $url) at the necessary places throughout the code, and URLs with underscores worked like a charm. As an Easter egg, try writing a tweet over 140 characters containing a URL where you replace an underscore with “t9WGb5” yourself, for example, “test test test test test test test test test test test test test test test test test test test”, then preview it on the Write Tweet page. Check the preview page for the short URL, i.e., and you’ll see that your “t9WGb5” was converted to an underscore before the long URL was even sent to, as an artifact of my kludge-like solution.

Couldn’t the tag balancing problem be approached in the same way? Of course it could. A simple modification to /wp-includes/formatting.php did the trick. Right at the start of the force_balance_tags function, I replaced “<?php” and “?>” with “[![?php” and “?]!]” using str_replace, as follows:

function force_balance_tags( $text ) {
     $text = str_replace(array(‘<?php’, ‘?>’), array(‘[![?php’, ‘?]!]’), $text);
     $tagstack = array(); $stacksize = 0; $tagqueue = ”; $newtext = ”;

Then, at the end of the function, I change it all back:

// WP fix for the bug with HTML comments
     $newtext = str_replace(“< !–“,”<!–“,$newtext);
     $newtext = str_replace(“< !–“,”< !–“,$newtext);
     $newtext = str_replace(array(‘[![?php’, ‘?]!]’), array(‘<?php’, ‘?>’), $newtext);
     return $newtext;

All this happens either before or after Exec-PHP executes. I’m not sure when, but it doesn’t matter. My goal of being able to use tag balancing with Exec-PHP has been reached. I now have $strip_tags set to true in the_excerpt_reloaded and “WordPress should correct invalidly nested XHTML automatically” enabled in Settings > Writing, and all I have to do is re-apply the hack when I upgrade WordPress. It’s amazing what thinking outside the box gets you.

I can’t actually write “[![?php” or “?]!]” inside any post on my site, because my hack will convert those strings to real PHP code and they won’t be displayed. How did I display the code above? My actual /wp-includes/formatting.php file uses underscores instead of exclamation points. How did I include the sniplets in the example post without the Sniplets plugin executing them? Breaking the parser with the &shy; HTML entity. Simple.

Earlier, I talked about the functions I use in my photo template to automate display of file size and Exif data. Here are those functions:

function fsze($f = ‘simplicity-stock.jpg’, $p =
     {$n = array(‘Bytes’, ‘KB’, ‘MB’, ‘GB’); $p = $p . $f;
     if(file_exists($p)) $b = filesize($p);
          else $b = ‘1000’;
     echo round($b/pow(1000, ($i = floor(log($b, 1000)))), 2) . $n[$i];}

function fprm() {
     return str_replace(‘photo-‘, ”, preg_replace(‘/-+/’, ‘-‘,
          preg_replace(‘/[^a-z0-9-]/’, ‘-‘,
          strtolower(trim(str_replace(array(‘?’, ‘…’),
          array(”, ”), get_the_title()))))));}

function fexf() {
     $exif = exif_read_data(‘/home/thripp/public_html/wp-content/’ .
          ‘blogs.dir/2/files/photos/’ . fprm() . ‘.jpg’, 0, true);
     $shutter = $exif[‘EXIF’][‘ExposureTime’];
     $fnum = str_replace(‘f/’, ‘F’, $exif[‘COMPUTED’][‘ApertureFNumber’]);
     $focal = $exif[‘EXIF’][‘FocalLength’];
     $iso = $exif[‘EXIF’][‘ISOSpeedRatings’];
     $date = $exif[‘EXIF’][‘DateTimeOriginal’];
     $date = str_replace(‘:’, ‘-‘, substr($date, 0, 10)) . ‘T’ .
          substr($date, 11);
     if(substr($date, 0, 4) < = 2007) {           $id = substr($date, 0 , 10) . '_' . substr($date, 11, 2) .           'h' . substr($date, 14, 2) . 'm' . substr($date, 17);}      elseif(substr($date, 0, 4) >= 2008) {
          $id = str_replace(‘-‘, ”, substr($date, 0 , 10)) . ‘-‘ .
          str_replace(‘:’, ”, substr($date, 11)) . ‘rxt’;}
     $md = str_replace(‘-‘, ”, substr($date, 5, 5));
     $hms = str_replace(‘:’, ”, substr($date, 11));
     if(substr($date, 0, 4) == 2004) {
          if(($md < 0404) || ($md == '0404' && $hms < 020000) ||           ($md > 1031) || ($md == ‘1031’ && $hms > 020000))
               $ldate = $date . ‘-05’;
          else $ldate = $date . ‘-04’;}
     if(substr($date, 0, 4) == 2005) {
          if(($md < 0403) || ($md == '0403' && $hms < 020000) ||           ($md > 1030) || ($md == ‘1030’ && $hms > 020000))
               $ldate = $date . ‘-05’;
          else $ldate = $date . ‘-04’;}
     if(substr($date, 0, 4) == 2006) {
          if(($md < 0402) || ($md == '0402' && $hms < 020000) ||           ($md > 1029) || ($md == ‘1029’ && $hms > 020000))
               $ldate = $date . ‘-05’;
          else $ldate = $date . ‘-04’;}
     if(substr($date, 0, 4) == 2007) {
          if(($md < 0311) || ($md == '0311' && $hms < 070000) ||           ($md > 1104) || ($md == ‘1104’ && $hms > 070000))
               $ldate = date(“Y-m-dTH:i:s”,
               (strtotime($date) – 18000)) . ‘-05’;
          else     $ldate = date(“Y-m-dTH:i:s”,
               (strtotime($date) – 14400)) . ‘-04’;}
     if(substr($date, 0, 4) == 2008) {
          if(($md < 0309) || ($md == '0309' && $hms < 070000) ||           ($md > 1102) || ($md == ‘1102’ && $hms > 070000))
               $ldate = date(“Y-m-dTH:i:s”,
               (strtotime($date) – 18000)) . ‘-05’;
          else     $ldate = date(“Y-m-dTH:i:s”,
               (strtotime($date) – 14400)) . ‘-04’;}
     if(substr($date, 0, 4) == 2009) {
          if(($md < 0308) || ($md == '0308' && $hms < 070000) ||           ($md > 1101) || ($md == ‘1101’ && $hms > 070000))
               $ldate = date(“Y-m-dTH:i:s”,
               (strtotime($date) – 18000)) . ‘-05’;
          else     $ldate = date(“Y-m-dTH:i:s”,
               (strtotime($date) – 14400)) . ‘-04’;}
     if(substr($date, 0, 4) == 2010) {
          if(($md < 0314) || ($md == '0314' && $hms < 070000) ||           ($md > 1107) || ($md == ‘1107’ && $hms > 070000))
               $ldate = date(“Y-m-dTH:i:s”,
               (strtotime($date) – 18000)) . ‘-05’;
          else     $ldate = date(“Y-m-dTH:i:s”,
               (strtotime($date) – 14400)) . ‘-04’;}
     if(substr($date, 0, 4) == 2011) {
          if(($md < 0313) || ($md == '0313' && $hms < 070000) ||           ($md > 1106) || ($md == ‘1106’ && $hms > 070000))
               $ldate = date(“Y-m-dTH:i:s”,
               (strtotime($date) – 18000)) . ‘-05’;
          else     $ldate = date(“Y-m-dTH:i:s”,
               (strtotime($date) – 14400)) . ‘-04’;}
     if(substr($date, 0, 4) == 2012) {
          if(($md < 0311) || ($md == '0311' && $hms < 070000) ||           ($md > 1104) || ($md == ‘1104’ && $hms > 070000))
               $ldate = date(“Y-m-dTH:i:s”,
               (strtotime($date) – 18000)) . ‘-05’;
          else     $ldate = date(“Y-m-dTH:i:s”,
               (strtotime($date) – 14400)) . ‘-04’;}
     if(preg_match(“///”, $focal, $m)) {$pieces = explode(‘/’, $focal);
          $focal = intval($pieces[‘0’])/intval($pieces[‘1’]);}
     if(preg_match(“///”, $shutter, $m)) {$pieces = explode(‘/’, $shutter);
          $shutter = ‘1/’ . round($pieces[‘1’]/$pieces[‘0’]);}
     echo $shutter . ‘, ‘ . $fnum . ‘, ‘ . $focal . ‘mm, ISO’ . $iso .
          ‘, ‘ . $ldate . ‘, ‘ . $id . “n”;}

Those were tough to write. PHP’s native functions for calculating the size of files believe that a kilobyte is 1024 bytes and a megabyte is 1024*1024 bytes, which is completely false and unacceptable. I had to write my own function to calculate proper file sizes. I take all my pictures with my clock set to Greenwich Mean Time, but I still want to display the time in local time (Eastern) with the GMT offset. I couldn’t figure out how to write a generic function, so I just did it for each year up until 2012, using the United State’s Daylight Saving Time rules. I’ll have to update the function in 2013, but I hear the world is going to end in 2012 anyway.

If you think this adds to my page load time, you’re probably right. But I use W3 Total Cache to completely cache each page of my blog, so it doesn’t matter.

Next summer, I’m going to China with my Mom. I will be leaving the Eastern time zone for the first time ever. I will definitely need to update the functions above, and I will probably have to specify the time zones manually for all the photos I post from the trip. Should I worry about that now? Of course not.

WiredTree Hybrid Servers Upgraded — Game-Changer for Web Hosting Industry

WiredTree Hybrid specs

I’ve been hosting all my websites on a WiredTree Managed Hybrid VPS Server since July 2009, and the plan has not changed a bit until this week. For the past year and a half, WiredTree offered 1GB RAM, 80GB disk space, 2TB bandwidth, and 1 processor core for $99 per month. Starting Monday, this plan has changed to 2GB RAM, 100GB disk space, and 3TB bandwidth, with no increase in price. These stats are real—WiredTree does not oversell and this resources are always reserved for your account. If you aren’t using all your RAM or disk space, nobody else gets to use it—it stays unused and immediately available to you.

Hybrid Servers are actually beefed-up Virtual Private Servers—the name VPS is not used because they provide the resources of a low or medium end dedicated server without the expense. For instance, a WiredTree server might contain two 1TB hard drives, 16GB RAM, and two quad-core processors. Such a server might host 7 Hybrid Server accounts, giving each 2GB RAM, 100GB RAID10 mirrored disk space, and a processor core. The remaining core, RAM, and disk space would be used for software called Virtuozzo, which partitions the server into virtual machines. Such a powerful server may cost under $400 a month to operate—WiredTree would get almost $700 from seven different clients. While offering the server directly to clients is an option, most people do not need and cannot afford such a powerful machine. A Hybrid Server is a much better option.

Prior to this, WiredTree Hybrid Servers were not a spectacular deal—you could find faster servers at cheaper prices elsewhere. Thousands of people choose WiredTree not for their rock-bottom prices, but for their superior uptime, customer support, and reputation. You can send a support ticket to WiredTree any time of the night and you’ll get a response in under 30 minutes. While other web hosting companies make a point of hiding their phone number, you can call WiredTree toll-free at 866-523-8733 with any questions or problems. Combining 24/7 custom service with the new Hybrid Server specs, WiredTree blows all other mid-range hosting companies out of the water. This is truly a game-changing announcement.

My website gets over 1000 visitors a day, and I host other websites such as Composer’s Journey and on this Hybrid server too. I also host the URL shortener here, which shortens 1.3 million URLs per month and receives over 10 million requests, including pageviews and API calls. is not simply a URL shortener—I display Google AdSense ads on every short URL in an iFrame, which requires PHP. This alone generates over $100 per month. The database is a single InnoDB table in a MySQL database with nearly 20 million rows. The size of the database is 3.2 gigabytes, and it’s never been corrupted. barely makes a dent in my Hybrid server’s resources.

WiredTree provides detailed statistics about your server. Here are just a few of those from my server, for the past month:

WiredTree Hybrid stats

The above stats are with the OLD server specs. I had 1.5GB of RAM because I used the coupon code HYBRIDFREE512RAM when I signed up. The spike on August 18 is when I did a full backup of my cPanel account including all files and databases, which totaled 7GB and took only 30 minutes. I only use 150GB of bandwidth a month tops, and that’s with lots of large Canon RAW files (10MB each) hosted on my server for direct download by the public. With the new upgrades, I could use 20 times the bandwidth and still be fine.

WiredTree says all existing hybrid customers will be upgraded within a month, but if you’re a new customer, you can get a hybrid server with the new specs right now. If you use this affiliate link, I will get one month of free hosting a month after you sign up. You can register as an affiliate yourself and receive 100% of the first month of any sales as a hosting credit or 75% to your PayPal account. This could potentially pay your hosting bill every month.

WiredTree Hybrid servers run CentOS 5, a Linux distro that is the defacto standard for VPS hosting. Apache, MySQL, PHP, Perl, Python, FTP, SSH, cPanel, Web Host Manager, phpMyAdmin, Cubemail, and plenty of other stuff is available out of the box, and WiredTree technicians watch your server for problems and improve its security. You can have WordPress set up on your own domain in under an hour, and if you don’t know how, you can put in a support ticket. They’ll even transfer your files from your old host for you if you provide your usernames and passwords (they are trustworthy and I often provide them my root password).

The Radified blog has a great guide to VPS hosting, focused on WiredTree, and you can read Mr. Rad’s experience in making the switch here. It’s 2 and a half years old, but besides better specs and cheaper prices, WiredTree hasn’t changed a bit.

This is straight from the WiredTree “Grove” admin pages:

“We have made major investments easily in the tens of thousands of dollars this year upgrading our Hybrid infrastructure, retrofitting existing servers, and introducing new servers to support these increased allocations and to ensure you are getting the best value for your money.”

Though I don’t know how many clients they have, I wouldn’t be surprised if they spent $100,000 on these upgrades. RAM is cheap, but it isn’t dirt cheap, especially if you want quality. WiredTree performs automatic nightly backups of all your files and has multiple layers of redundancy, so giving a customer 20GB extra disk space might require 100GB extra disk space in their infrastructure. Ditto for RAM and bandwidth.

WiredTree has disabled the coupon codes HYBRIDFREE512RAM and 10PERCENTOFF on the new Hybrid plans, presumably because the prices are already rock-bottom, but you can still receive a 5% discount by paying for a year in advance. This is what I do, and I will be paying them $1128.60 in February unless I get a bunch of affiliate commissions. Start off paying by the month until you find out how special WiredTree is.

Unless you have a large, successful website already, you should start out with a Virtual Private Server ($49 per month) or even shared hosting, which WiredTree does not provide. At the VPS level, there are many WiredTree coupons available—don’t sign up without one.

You can host an unlimited number of websites on all WiredTree’s plans. Your only limits are how much RAM, disk space, bandwidth, and CPU power these sites consume. If you have a bunch of small sites, there’s no reason to pay a hosting bill for each one. Consolidate them under one VPS plan. You can even use your own DNS name servers like NS1.THRIPP.COM and NS2.THRIPP.COM.

While the new Hybrid Servers were announced two days ago, I couldn’t find any articles in the blogosphere about this ground-breaking change—just verbatim copies of the press release. I’m sure this will change before the week ends, and WiredTree will become one of the world leaders in web hosting. They may even need to open a second data-center outside of Chicago.

Check out WiredTree today. Even if you already have a good web host, WiredTree is better.

Thripp 2010: Results for August

It’s been three weeks since I started my Thripp 2010 project. I’ve posted one photo weekday from before 2010 here, one photo per weekday from 2010 on Thripp Photography 2010, and one comic per weekday on I See a Fish. I have only posted seven compositions on Composer’s Journey because of the difficulty of composing music. My plan is to only post three compositions per week, so at the end of 2010 I should have 59 compositions.

Though this was not part of my plans originally, I have released the first updates to Tweet This since September 2009. This plugin for WordPress integrates Twitter with your blog, allowing your readers to tweet your articles with a click and allowing you to automatically tweet new and scheduled posts. Version 1.7.1 has support for OAuth, a new options menu design, and many fixes. The Tweet This page gets 50% more visitors than my blog home page, has more back-links, and has a Google PageRank of 6/10 compared to the Thripp Photography home page’s rank of 5/10, so this should help me meet my revenue and traffic goals. I am planning to release three more major versions of Tweet This this year (1.8, 1.9, and 2.0).

On Sunday, August 15, I set three objectives for these 20 weeks:
1. Get 50,000 absolute unique visitors in total for the three sites (track with Google Analytics).
2. Earn $2000 in Google AdSense revenues (including other sites such as
3. Increase the Alexa ranking of to 40,000.

The first one is a cinch. Google Analytics logged 8139 absolute unique visitors on alone from Aug. 16 through Aug. 31, or 508 per day. If this keeps up, I will end 2010 with 70,000 unique visitors.

The second objective is not going well. I made $172.87 in AdSense revenues from Aug. 16 through Aug. 31, or $10.80 per day. To meet my goal of $2000, I have to make $14.49 every day. To get back on track, I have to make $16.46 per day in September, or $493.67 for the whole month. My best month for AdSense so far was March 2010, when I made $452.40. Unless people start donating, I will have a hard time reaching my goal. I added an ad unit at the top of the each page below the header, but it hasn’t increased my revenues much. I tried AdBrite for a day. I received 2000 impressions and ZERO clicks, making 12 cents. Unbelievable. They might just be cheating me, not counting any clicks. I won’t use them again. I’ve even added a donation widget to my sidebar, but no luck. Perhaps I’m not providing enough value?

The third objective also looks hopeless. My Alexa rank has only increased 5K to 65K, and my rank for the past week is way down at 73K. If you look at my one-week graph, my rank spikes to 35K on Aug. 28, and then drops like a rock. It’s around 100K these past few days. I have no idea what happened.

I must redouble my efforts these next four months if I want to succeed. It’s not enough just to produce photos, music, comics, plugins, and writing. I have to promote myself. I’m going to start commenting on other blogs, networking on Twitter and Facebook, and sending out emails. September will be better.

Tweet This 1.7 Released

Today I released Tweet This 1.7, the first update to my WordPress plugin in nearly a year. This version adds OAuth support, and it is an important upgrade because Twitter will be disabling basic authentication tomorrow, Aug. 31, 2010. I’ve also added support for the API and fixed many bugs, including problems with automatic tweeting.

Tweet This 1.7 is also available on the WordPress plugin repository and it has been downloaded 100 times since I released it an hour ago. Twitter requires each user of Tweet This to fill out a lengthy and complex application registration form and then copy and paste four API keys to the Tweet This settings, all of which long and confusing, like “5151540-ADGJeaa-dgaiojt-3ugeaei-ghq75gj-dwerty.” Even Alex King, creator of Twitter Tools, has complained about it. Unfortunately, it’s my only option, so I’ve included detailed instructions on the Tweet This options page.

Please leave me feedback and bug reports, as I will be actively developing Tweet This over the coming months.

Thripp 2010

Thripp 2010

I’m launching two new websites today: Thripp Photography 2010 and Thripp 2010 reuses what used to be the development blog, and is an online comic about dating and relationships.

From now on I will only post photos from 2009 or earlier on Thripp Photography and all photos from 2010 or later will go on

For the next 20 weeks I will post one pre-2010 photo per weekday on Thripp Photography, one 2010 photo per weekday on, one musical composition per weekday on, and one comic per day on I already have 8 weeks of photos prepared in advanced and 4 weeks of comics. Composing music will be the hardest part. It takes 10 times as long to write a piece of music as it does to prepare a photograph or write a comic. I have nothing planned for the weekends, but I may write something from time to time.

In all I will post 200 photos, 100 compositions, and 100 comics from 2010-08-16 through 2010-12-31. I’m calling this project “Thripp 2010.” I am also planning on releasing four albums on Today I released my first CD, Inferno.

The photo for Thripp 2010 is “Bridge Over Troubled Water” and the theme is “Inspired Creativity.” The photo “Bridge Over Troubled Water” will be posted to Thripp Photography 2010 on 2010-08-24. My objectives are:

1. Get 50,000 absolute unique visitors in total for the three sites (track with Google Analytics).
2. Earn $2000 in Google AdSense revenues (including other sites such as
3. Increase the Alexa ranking of to 40,000.

Getting 50,000 unique visitors will be about a 10% increase over what I get currently. In the past four and a half months, I’ve made $1570 from Google AdSense, so I will have to increase my income by 22%. My Alexa ranking is about 70,000 now, but for the past month only it is 54,000. I will have to increase traffic from visitors using the Alexa toolbar by 26% compared to the past month, and sustain it for the months of October, November, and December. Since Alexa only counts the past three months, whatever happens in September or the remainder of August doesn’t matter.

For the first time in three years of on-and-off blogging, I am going to play this game dead seriously. If I don’t commit myself fully, I will never be able to make enough money to live comfortable from only my websites. Starting tomorrow, you’re going to see some serious shit.

PHP Magic

On my new site I post my musical compositions like this:

Ode to Ted Kennedy MP3, 1:52, 1.35MB
Ode to Ted Kennedy MIDI, 7.69KB
Ode to Ted Kennedy PDF, 25.47KB
Ode to Ted Kennedy Score (Sibelius 6), 40.85KB

I upload each file through WordPress to the /files/ directory with subdirectories for years and months enabled. The filename is the title of the musical composition followed by my initials and the date of posting, and I use hyphens as spacers. I use a modded version of WPaudio to turn MP3 links into JavaScript-based music players.

Wouldn’t it be nice if I could automate the creation of these links instead of having to type the filenames four times, the title four times, the size of each file, and the length of the MP3?

The first step was to download and enable Exec-PHP so I could use PHP code in posts. Then I checked “Disable the visual editor when writing” in my profile and under Settings > Writing I unchecked “WordPress should correct invalidly nested XHTML automatically.” Next, I wrote this function and added it to my theme’s functions.php file:

function flnk($e = ‘mp3’, $t = ‘MP3’, $a = ”, $c = ”, $l = ”) {
if($c != ”) $c .= ‘, ‘;
$d = wp_upload_dir();
$n = array(‘Bytes’, ‘KB’, ‘MB’, ‘GB’);
$b = ‘/’ . get_the_time(‘Y/m’) . ‘/’ . basename(get_permalink()) .
‘-rxt-‘ . get_the_time(‘Ymd’) . $a . ‘.’ . $e;
$p = $d[‘basedir’] . $b;
$u = $d[‘baseurl’] . $b;
if(file_exists($p)) $f = filesize($p);
else $f = ‘1000’;
if($e == ‘mp3’) {
$i = round(($f/(12000))-.5);
if($l == ”) $m = floor($i/60) . ‘:’ .
str_pad($i % 60, 2, 0, STR_PAD_LEFT);
else $m = $l;
$m .= ‘, ‘;
if($e != ‘mp3’) $z = ‘ target=”_blank”‘;
echo ‘<a href=”‘ . $u . ‘”‘ . $z . ‘>’ . get_the_title() . ‘ ‘ .
$t . ‘, ‘ . $c . $m . round($f/pow(1000, ($i = floor(log($f,
1000)))), 2) . $n[$i] . ‘</a>’ . “n”;

This function gets the post title, post date, and slug [basename(get_permalink())] to assemble the title and URL. It uses PHP’s filesize() function to get the size of the file, then converts it to a number like 500.00 and expresses it in Bytes, KB, MB, or GB depending on the size. If the file is an MP3, the length is also displayed by dividing the file size by 12,000 and subtracting 0.5 seconds for excess data in the MP3 file. Then the number is rounded and the seconds are padded to two digits (2:3 becomes 2:03). This returns an accurate length if the file is 96kbps CBR (most of mine are). If the file is NOT an MP3, target=”_blank” is added to the link so it opens in a new window (MP3s are handled by the WPaudio plugin) Finally, the link is echoed.

For the links I displayed at the beginning of this post, all I have to do now is upload the files, title the post, write a description, choose categories, and then copy and paste this code to the post:

<?php flnk(‘mp3’, ‘MP3’); flnk(‘mid’, ‘MIDI’); flnk(‘pdf’, ‘PDF’); flnk(‘sib’, ‘Score (Sibelius 6)’); ?>

The function has 5 arguments: the file extension ($e), filetype title ($t), text to append to the filename ($a), special description ($c), and custom length ($l). Usually I only use the first 2. If I used a different bitrate for the MP3 file, I override the length like this: <?php flnk('mp3', 'MP3', '', '', '1:21'); ?>. I’ve only used the third and fourth functions on the piano version of Inferno as follows:

<?php flnk(‘mp3’, ‘MP3’, ‘-piano’, ‘Piano Only’); flnk(‘mid’, ‘MIDI’, ‘-piano’, ‘Piano Only’); flnk(‘pdf’, ‘PDF’, ‘-piano’, ‘Piano Only’); flnk(‘sib’, ‘Score (Sibelius 6)’, ‘-piano’, ‘Piano Only’); ?>

The above code generated this output:

Inferno MP3, Piano Only, 1:46, 1.28MB
Inferno MIDI, Piano Only, 8.62KB
Inferno PDF, Piano Only, 38.07KB
Inferno Score (Sibelius 6), Piano Only, 43.83KB

A little work now will save me a lot of time in the long run. I only have to type the title and description for each composition I post now. While this will increase my server’s load and slow down my website slightly, I can always use caching if becomes popular.

New Permalink Structure

I changed the WordPress permalink structure for this blog from “/%postname%-%post_id%” to “/%year%/%monthnum%/%postname%/”, after nearly three years with the old URLs. This is what most WordPress blogs use, and I understand the wisdom of using a trailing slash which indicates directory status with non-virtual URLs, implies the end of the URL, and is expected by most users. Including the post ID was a stupid mistake. I was copying what deviantART does in its post URLs, but the month and date are far better than a meaningless number.

This also matches what I did on my new blog, Composer’s Journey.

The hard part was redirecting all the old URLs to the new URLs. I ended up changing the core file /wp-admin/includes/post.php: where it says “posts_per_page=15” I substituted “posts_per_page=500”. Then I opened a copy of my Manage Posts screen with the old URLs, changed permalink structures to the new URLs, opened a new tab with the Manage Post screen, changed back to the old permalinks, and started copying and pasting the permalinks into a CSV file which I imported into the Redirection plugin. I redirected the original posts and the printable version links, but I was not able to get the comment RSS feed links to redirect (got stuck in an endless loop). No one uses those, fortunately. Copying and pasting 848 URLs was no picnic.

Enjoy the new URLs!

What printer should you buy for your office?

My Mom just sent me this question:

Dear Son,
My coworker Mark asked me if you have any good suggestions on laserjet printers. His printer at home ran out of ink and he doesn’t want an ink jet. If you know of any good deals out there, could you let him or me know?

Love, Mama

My answer:

Dear Mom,

I used to recommend Lexmark and HP, but I no longer recommend them because they gouge on toner in their low-end laser printers. I now recommend BROTHER.

I have a Brother HL-2140 and I like it. I paid $50 on sale (OfficeMax)… it’s $80 on Amazon now. Watch for a sale. It prints fast and clean. While it doesn’t duplex, you can just put pages face up, top toward you to print on both sides manually. I’m still on the starter cartridge (1000 pages) but you can order third-party replacement cartridges online for $30 shipped (refilled), which print 2600 pages. Much cheaper than new Lexmarks which have no refilled cartridges… $100 a cartridge with them. Brother is usually cheaper.

If he orders it have him order through this link:

Then I get 4% ($3.20) and it costs him the same. That link puts an Amazon tracking cookie on your computer… I get a 4% commission on anything you order within 24 hours as long as you don’t delete your cookies.

Black and white (monochrome) laser printers are the de facto standard for printing text and documents. They use them exclusively at my college. Inkjets don’t even compare. Laser printing is one-tenth the cost of inkjet and the text quality is better. It’s also much faster… I can print a 20-page document in under a minute.

The HL-2140 is really for 8.5*11 paper… I think it’s not good with envelopes or other sizes.

Love, your son,

I haven’t printed a document with an inkjet printer in over 2 years. Photos are great on inkjets. However, if you’re going to print walls of text, you need a black-and-white laser printer. I have one of both.

As for printing a lot of photos… you’d be best to go through an online printer like Snapfish or Shutterfly. They produce resin-coated chemical prints from a digital source using a laser, usually with very expensive Fuji Frontier machines (expose and then develop, stop, fix, wash, all automated in darkness). It’s cheaper, the quality is miles beyond inkjet prints, and the prints are WATERPROOF… I can put one of my 4*6 prints from Snapfish underwater for hours. Then when I hang it out to dry, it’s just fine. Awesomeness.

Color laser printers also exist… but I wouldn’t recommend them for photos. I also wouldn’t recommend them for the office, unless you want to spent $500 or more. I have a Lexmark C534N ($700 printer I got free after rebate 2 years ago), and after printing 1500 pages it just says “service fuser”… I don’t know what to do. Color lasers are more expensive per page, even in black and white mode. They’re expensive, large, heavy, complicated, and failure-prone. In the office, stick to black and white laser printers.

Trivia: toner is finely ground bits of black plastic (also: yellow, red, and blue plastic in color laser printers). The laser printer etches toner onto a drum with a laser. Then, it literally fuses the toner to the paper at a temperature of up to 400 degrees Fahrenheit. The paper doesn’t catch on fire because it passes through the fuser in just a few seconds. But it comes out nice and hot…

What printer do you recommend? Post a comment!