Consolidation

I’ve decided I’m going to consolidate my other websites, thripp.com/blog, composersjourney.com, and iseeafish.com under the richardxthripp.thripp.com domain. Nobody goes to them anyway… they don’t have the PageRank to rank high in Google’s search results… this site does, so why should I try to fight Google?

It’s really better to have all your sites under one domain anyway. I’m not going to merge daytonastate.org, since its value lies largely in the domain itself (similar to daytonastate.edu), but my other websites will be consolidated here including previous content over the next few months… I might even sell off the domains! But probably not.

On a sad note, today my half-sister Anna would be 11 years old. I only met her once, and she passed away in an accident at six months. She died on Father’s Day… 1999-12-16 / 2000-06-17 never forget.

I’ve been having a lot of fun tutoring and meeting people at Daytona State College even though my classes ended Oct. 22, 2010 since I took Fall A classes. Next semester I want to be a tutor at the Academic Support Center or Student Disability Services for math and English… should be fun and help me to relate to people.

I met Trina Chakravarty at Rotary Int’l. last week. She was Miss India USA 2005 and Miss India Worldwide 2006, she’s going to be an M.D. (medical doctor) next year at 24, and she even writes a blog! So amazing…

Richard X. Thripp, Trina Chakravarty

I have been slacking posting newly re-edited photos here, but I’ll have some this weekend.

Finally, I have decided to disable Infolinks on my sites. Infolinks is an ad network that double-underlines words on your site with ads. They are just too annoying, and they make next to nothing anyway… $0.10 a day tops. Google AdSense, AdBrite, and Amazon Associates create more revenue … even Chitika does.

Enjoy the cold weather while it lasts. :)

Updated 2010-12-20: I’ve re-enabled Infolinks after being contacted by the Infolinks team… Tanya W. is working to improve my revenue which so far has been only $1.99 for 51 clicks and over 16,000 impressions in 21 days… we will see how this goes.

Virtual Thripp.com Subdomains

I’ve set up some virtual Thripp.com subdomains for pages on richardxthripp.thripp.com that used to subdirectories. All the old URLs 301 to these new URLs. Check out the first batch of subdomains:

about.thripp.com
contact.thripp.com
domains.thripp.com
index.thripp.com
gallery.thripp.com
portfolio.thripp.com
portraits.thripp.com

All of these are for me only and are completely part of richardxthripp.thripp.com. In 2008, I intended Thripp.com to be a social network built on WordPress MU with subdomains for each user, but that never worked out so I feel comfortable owning the *.thripp.com namespace for my own projects now. I will never be changing the URL of this blog from richardxthripp.thripp.com since it’s been that way for so long, though.

This was actually very hard to implement. I’m using WordPress MU 2.7 and the WP Subdomains plugin, but I had to do hacking on both and I can’t get any subdirectories on these virtual subdomains to work so I have to use query strings. For example, gallery.thripp.com is paginated so page 2 is gallery.thripp.com/?page=2/ because I couldn’t get gallery.thripp.com/2/ to work. However, I’m glad I set this up since I will be using Thripp.com subdomains for many pages and ad campaigns in the months to come.

Banned from Google AdSense

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

Hello,

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.

Sincerely,

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 Th8.us 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 About.com 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=”http://thripp.com/files/photos/flash.jpg” 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 http://www.google.com/!” becomes “Check out http://www.google.com/ !”. 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. http://en.wikipedia.org/wiki/South_Africa gets sent to the URL shortener http://en.wikipedia.org/wiki/South, which gets converted into http://bit.ly/bzLvSK_Africa, 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 http://en.wikipedia.org/wiki/Southt9WGb5Africa”, then preview it on the Write Tweet page. Check the preview page for the short URL, i.e. http://bit.ly/cRLAis+, and you’ll see that your “t9WGb5” was converted to an underscore before the long URL was even sent to Bit.ly, 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 =
     ‘/home/thripp/public_html/wp-content/blogs.dir/2/files/photos/stock/’)
     {$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 Thripp.com on this Hybrid server too. I also host the Th8.us URL shortener here, which shortens 1.3 million URLs per month and receives over 10 million requests, including pageviews and API calls. Th8.us 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 Th8.us 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. Th8.us 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.

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 Bit.ly 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.

PHP Magic

On my new site ComposersJourney.com 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 ComposersJourney.com becomes popular.

Your Blog is Not a Community

Most blogs consist of one person commenting on the world, and a whole bunch of people passing by, spending five minutes to skim several posts, and perhaps making a comment or two. These people move on to never return, and they are replaced by more people who in turn do the same.

While blogs are typically considered more communal than typical websites, they may in fact be less so. Other websites have forums which receive hundreds of posts per day from established and respected members. That is a community. Blogs have comments. If you’re lucky (like with this blog), they are threaded with email notifications. This has the potential for community building, as people may make comments, reply to other comments, and return to reply again. However, it generally does not create community. Most people still visit once and only once.

Some bloggers try adding a forum. I did this, and the sad reality is that you will get no participation. For every 100 people that visit your website, one person will make a comment. And for every 100 people who comment on your blog, one person will sign up and post on your forum. Even if you put a widget in your sidebar with the latest forum topics, you’ll still get little to no participation. The forum is basically a separate website, one that will receive no benefit from the fame of your blog. Unless your blog is so popular that you’ve turned off comments, forums are a waste of time. You must chose: forums or comments. One or the other. Not both. On a popular blog, you may be better off disabling comments and creating a forum requiring registration. It cuts out the noise.

Bloggers used to require registration to comment, but fortunately no one does this anymore. It is so stupid and pointless now that spam filtering is so good. There are only three purposes for registration: to track people for marketing, to allow for user profiles that other members can read, and to track comments. WordPress allows none of these. BuddyPress does, and there are plugins, but no one is using those. Registration doesn’t create a feeling of community. It creates a feeling of annoyance.

RSS feeds get people to come back for more, but most people who use RSS feeds are lurkers. You won’t get a comment from them. You may get thousands of pageviews over a period of months, but you won’t get comments and you won’t get community participants.

Responding to comments helps build community, but don’t respond to everything. Simple comments like “your work is great” do not deserve a thank you. That is boring and unneeded. I no longer reply to such comments. My time is better spent writing new blog posts.

Most comments will be people looking for help, and they will be in response to problem-solving posts that didn’t solve their problems. A third of the comments on this blog have been on my Tweet This plugin (most are archived), and they have not been thank-yous so much as requests for help. These are not people wanting to participate in a blog community: these are people who want their problems solved so they can move on with their lives. No community content there.

WordPress MU does not build communities. Many people try and many people fail. All the blogs are separate—all the blog posts are stored in separate database tables. There’s no way to even aggregate them effectively without creating a mirror of them in a unified table, and this is complicated to set up. It is also unwieldy and wasteful. There is no linking blogs together in WordPress MU. They are islands. When you host a WordPress MU site, you are not a community leader. You are a web host.

As a blogger, you are a publisher, not a community leader. Don’t think of your blog as a round-table. Think of it as a newspaper. Yes you may feature letters to the editor, but remember who is in control and who leads the discussion. If you aren’t producing new blog posts every week, whatever “community” you have (which is really just visitors) will disappear immediately. It did when I left this blog for six months. It will for you too. No big deal. It can be quickly rebuilt. Communities take a long time to build, and if you alienate your loyal readers your site goes down the tubes. Blogs aren’t communities, so if you alienate some people (and you will), new people will replace them. Don’t expect anyone to write your posts for you or come up with ideas for you. It’s all on YOU. YOU must do it all YOURSELF. No one will help you. When you accept that you have no community to back you, you accept complete responsibility for the success of your blog. That is power.

My photos on the HTTP 500 Internal Server error page

I made a custom Internal Server Error page for the Thripp.com network, with all the photos from my portfolio. Error pages are fun again. :smile:

I put a lot of ads there too, so I can monetize the outages. Plus, the links are to the photos on my jpgmag.com gallery, and all the thumbnails are on Photobucket, so the page is light-weight, won’t chew up bandwidth, and makes my photos accessible when the database is down. It’s only 10KB!

I posted this to digg too:

Check out this HTTP 500 page; instead of being rudely interrupted with a cryptic error message and an accusation that you broke the server, on Thripp.com, you’re greeted by beautiful photography (and plenty of ads to boot).

Enjoy. :cool: