Is your Fluid app is too slow? Try nativefier instead

I have used Fluid for years to create single-page native web applications that run on my Mac. I have one for Help Scout, I have another for Trello, but I have noticed a problem: when replying to tickets in Help Scout, I would experience serious lag. Letters would appear hundreds of milliseconds after I typed.

I thought it was an issue with my computer, but I recently got an iMac Pro and it’s still happening, so I know that’s not the problem!

I tried Epichrome instead (like Fluid but using Chrome instead of Safari as the base), and that wasn’t any better.

Enter nativefier. Instead of using Safari or Chrome, it builds a single-page “native” web application using Electron, the same library that runs Slack and many other cross-platform native-ish web apps. nativefier has been working great.

So if you’re experiencing typing lag while using Fluid or Epichrome, check out nativefier!

The Future of WordPress

I will be presenting the WordCamp Denver 2017 keynote on August 26, 2017. It’s a privilege, and I’m looking forward to it! If you don’t have tickets yet, it’s not too late—get a ticket nowSee you soon!

I will update this post with the slides once they are available, and I will also have “show notes”—a list of links I will reference during the talk.

This post was written using Calypso.

Using Tweets to post more regularly

I think the pendulum of social media may have swung for me back to self-publishing. I hope so; I make my living on WordPress, and I love WordPress. I want to control my own content and don’t want to lose the timeline of my thoughts.

Perhaps the domain name being associated with my business adds just enough pressure to prevent me from posting. I did just buy, so maybe I’ll start a personal blog there.

I need to practice writing more often. Content is the biggest missing piece of the GravityView business.

So now, I’m creating draft posts from Tweets (when they’re not replies). That’ll give me plenty of momentum to continue writing on the website.

(And yes, I’m sure there’s a plugin for this. For now, this is better than nothing.)

Gwen Ifill

Gwenn Ifill

I did not know Gwen was sick. I didn’t know she had cancer. On Monday, she died.

I respected her and found comfort in her presence. I trusted Gwen to tell me the truth, to find humanity in any situation, to always reflect appropriate levels of concern.

I trusted Gwen Ifill completely. Not because she was on TV, but because she did not hide who she was: she broadcasted it. She was a complete person who was honorable and eminently professional.

Multiple times every week, before dinner, my wife Juniper and I watch the PBS NewsHour. We enjoyed saying hello to Gwen and Judy—out loud!—from our couch. We often would comment to each other that “Gwen and Judy are the best at what they do” and “there is no one else like them.” Then, turning back to the news, Juniper and I would watch Gwen professionally deliver the events of the day with heart and enthusiasm.

Now that she’s gone, I know that Gwen was my role model. She displayed strength, dignity, and professionalism, as well as strong steady passion for her work, kindness, and playfulness.

Thank you, Gwen, for being you.

How to fix UTF-8 filename issues when using wp_handle_upload()

PHP said the file didn’t exist. Except it did.

file_exists() wasn’t working for a file uploaded using wp_handle_upload(). It worked for every other file, except for one provided by a German customer.

I confirmed the following:

  • The file did exist in the correct wp-uploads sub-directory
  • The file had correct permissions
  • The directory and its parents had correct permissions

I was stumped.

Then I renamed the file

I converted indlæsning to indlaesning and it worked. The problem was with UTF-8 characters in the filename.

But how can this be? Let’s see where the file name comes from:

  • _wp_handle_upload() calls
  • wp_unique_filename() to generate a unique file name, which calls
  • sanitize_file_name() to prepare the file name
  • sanitize_file_name() then checks against a list of special characters that are not allowed in file names:
$special_chars = array("?", "[", "]", "/", "\\", "=", "", ":", ";", ",", "'", "\"", "&", "$", "#", "*", "(", ")", "|", "~", "`", "!", "{", "}", "%", "+", chr(0));

This list of characters can be modified using the sanitize_file_name_chars filter, but that seemed more complicated than I wanted.

The sanitize_file_name() function also includes a sanitize_file_name filter, which allows you to modify the name of the file after it’s already been sanitized.

Luckily, WordPress already has a function to convert other UTF-8 characters into Latin equivalents: remove_accents(). I used that to convert the filename into something file_exists() could handle.

Here’s how to fix UTF-8 issues with wp_handle_upload()

That converted the filename from: indlæsning.csv to indlaesning.csv. Note that the æ character got converted to ae.

The result? Finally, file_exists().

Restoring VVV functionality to Pressmatic

I switched from developing using Vagrant with VVV to using the new Mac app Pressmatic. I’ve been very happy, and so has my Mac—the dev environment runs much faster and my computer has been working a lot less. Less fan noise is good.

The server environment that Pressmatic uses don’t have some basic stuff that I needed to maintain compatibility with my setup. This is a running list of items that I’ll update as I come across more requirements:

  • wget
  • Subversion
apt-get install wget subversion curl php5-cli git
apt-get update

To set up unit testing, we’ll need to do a few more things. The following are taken from Tom McFarlin’s great article on unit testing with Pressmatic.

# Make sure required libraries are installed
apt-get install curl php5-cli git

# Install Composer
curl -sS | php -- --install-dir=/usr/local/bin --filename=composer

# Tell Composer what version of PHPUnit to run
composer global require "phpunit/phpunit=4.8.*"

# Tell the server where to find Composer
export PATH="$PATH:$HOME/.composer/vendor/bin"

Oh My Zsh!

I love Oh My Zsh; it’s a simple way to make your shell console a lot better. A big must-have for me is improved directory navigation: I don’t want to prefix changing directories with cd [...]; just let me type ../!

Here’s the code to install it:

apt-get install zsh

# Install oh-my-zsh
sh -c "$(wget -O -)"

Then restart your console and you should be running Zsh. If not, type zsh.

Version 4.0 of the Constant Contact Plugin

I’ve been working on releasing a new version of the Constant Contact plugin for months, and it’s finally ready. The result: faster, more reliable, more features, and did I mention faster!?

The Form Designer, inline editing, and EventSpot are all 100% better. I highly recommend upgrading.

This plugin requires PHP Version 5.5 or newer. If you have a lower version, you will be presented with instructions on upgrading your installation.

Update: Now on

Download Version 4.0 from

Why isn’t this on yet? doesn’t allow code to use PHP 5.4 or newer. This will be fixed soon, but until it is, please download the plugin here.

Once fixes this issue, I will update this post, and the plugin will resume auto-upgrading as usual.


  • Version: 4.0.1
  • Released: April 8, 2016
  • Compatible with: WordPress 4.5

Download Constant Contact for WordPress


4.0.1 on April 8, 2016

This is a major update that requires PHP 5.5 or higher. This was needed in order to use the latest Constant Contact code.

  • The Admin now looks great on mobile devices!
  • Constant Analytics has been removed. The authentication process changed significantly, so it was no longer working properly.
  • Added: If a contact exists in the site, link to their profile page from their single Contact page
  • Improved: URLs and emails are now links in the single Campaign page
  • Improved: Inline edit is much faster
  • Added: Campaign summary to the top of single Campaign pages
  • EventSpot:
    • Embedding single events using the shortcode with onlyactive enabled now shows a “The “{title}” event is no longer active.” message.
    • Maps now link to Google Maps SSL
    • Location output includes Address 2 and Address 3, if set
    • Fixed: directtoregistration shortcode setting wasn’t working (“Link directly to registration page, rather than event homepage”)
    • Fixed: Added caching for if Constant Contact account has access to EventSpot
  • Form Designer:
    • New simple default form design
    • Responsive design fits better to all screen sizes
    • Visual feedback when the form is being updated
    • MUCH improved speed when designing a form
    • No longer slows down when processing an update
    • Change background, border, padding settings live
  • Fixed: Logs not being pruned. This could lead to thousands of log posts in the database, slowing down the site.
  • Fixed: Fix fatal error when updating lists in User Profiles
  • Fixed: Improved Form Designer speed when WP_DEBUG is defined
  • Fixed: Admin pages now only process when they’re supposed to
  • Removed: Phone number validation. The phone number validator library was silly big.
  • Tweak: Show list name in single List page
  • Tweak: Add “Status” column to Campaigns table
  • Tweak: Only “Active” users now shown by default in Contacts
  • Tweak: Filtering Contacts by status now loads new request
  • Fixed: Delete caches when de-authenticating plugin
  • Tweak: Allow Draft events to be visible to administrators

Developer Notes:

  • Fixed: The “%%id_attr%%placeholder wasn't getting replaced properly when generating list HTML inKWSContactList`
  • Fixed: Prevent logs from being written during Form Designer AJAX
  • Fixed: Removed deprecated wp_clone() function
  • Fixed: include attribute wasn’t respected in KWSContactList::outputHTML()
  • Tweak: Improved error handling for errors returned by Constant Contact
  • Tweak: Refactor LESS files for admin CSS
  • Modified: Second parameter passed to cc_event_map_link is now a \Ctct\Components\EventSpot\EventSpot object
  • Modified: Removed third parameter passed to cc_event_map_link
  • Added: ctct_oauth_uri_base filter to use your own oAuth domain. See the filter inline docs for more information.

Fixing JSON Parse Error in WordPress Plugins

If you write WordPress plugins and make AJAX requests, you may be familiar the dreaded Javascript error: SyntaxError: JSON Parse Error: Unrecognized token '>'

SyntaxError: JSON Parse Error: Unrecognized token '<'

Why? Why!?!

What it means is that the response your code expected is screwed up because a plugin barfed PHP warnings into the admin-ajax.php ventilation system.

When WP_DEBUG is on, admin-ajax.php responses can include junk HTML output from PHP warnings, like:

<br />
<b>Notice</b>:  Undefined offset: 0 in
<b>/wp-content/plugins/im-gonna-break-ur-ajax.php</b> on line
<b>666</b><br />

The fix? Catch exceptions, then exceed expectations

The way to fix this is to wrap the jQuery.parseJSON() function in try/catch. That will make sure that the code doesn’t fully blow up.

try {
  jQuery.parseJSON( response );
} catch( exception ) {
  console.log( exception );

That will prevent your code from breaking, but it won’t make your code work.

The cause of the code breaking is the junk HTML at the beginning on the AJAX response. So, what we want to do is:

  1. Check for a valid JSON response
  2. If the JSON is invalid, strips all characters until finding a JSON-style opening of {".
  3. Check the newly stripped string to see if that is valid JSON
  4. If valid, return the JSON. If not, return an error message.

Here’s the code to achieve that:

Let me know what you think, and please fork the Gist if you have any improvements!

Wanted: Intermediate/Advanced PHP Developers for Ongoing Freelance Work

Are you a self-motivated intermediate or advanced PHP freelance developer? Want to work on taking WordPress plugins to the next level?

I want to work with for someone who is interested in contract or hourly work to work with on GravityView, IDX+, and my other WordPress plugins. There is lots of work to be done. We currently have a team of 3 people working on the plugins, and I’m looking to expand my development and support team.

What you would be doing:

  • Develop additional functionality for existing plugins
  • Refactor existing code – implement appropriate coding patterns
  • Help squash bugs

What we’re looking for:

  • Good code – Write code with well-conceived structure
  • Problem solving – Figure out solutions that are best-practice and maintainable
  • Good communication – Check in when milestones are reached and when you have questions or delays
  • Intermediate to advanced PHP skills (With lots of OOP experience)
  • Experience with WordPress is a plus (familiarity with actions/filters/functions)
  • Experience writing unit tests with PHPUnit is a plus

If you are interested and feel like you would like to work with us, please fill out this form:

Get in touch to work with us:

  • Please check each box to show you've read what we're looking for!
  • What project best shows your abilities, and why?
  • Helpful, but not required.
  • This field is for validation purposes and should be left unchanged.

How to use your own widget icon in the WordPress Widget customizer

Customize WordPress Widget IconIn developing deeper integration with the Customizer functionality of WordPress, I wanted to use a custom icon for my IDX+ plugin’s widgets.

By default, WordPress defines a list of icons using their dashicons icon set and tries to guess the best icon for your widget based on the CSS class of your widget.

Check out the CSS in customize-widgets.css starting on line 415.

For instance, if your widget’s CSS class contains “music”, “radio”, or “audio”, you will have the format-audio dashicon applied to your widget.

How to change the widget icon

Using Dashicons

Note: In order to choose a new icon, go to the Dashicons website and click on the icon you want to use, then click on the “Copy CSS” link to get the correct CSS content value.

#available-widgets [class*=YOUR_CSS_BASE] .widget-title:before{
    content: "\f217"; /* <-- replace this value */

Using your own icon font

#available-widgets [class*=YOUR_CSS_BASE] .widget-title:before{
    font-family: idx-plus!important; /* <-- replace this value */
    content: 'd'; /* <-- replace this value */

If you want the icon to change color when it’s hovered over, use the following code:

#available-widgets [class*=YOUR_CSS_BASE]:hover .widget-title:before{
    color: #7da838!important; /* <-- replace this value */

I hope this helps!


Have you ever wanted to take a form submission and show the results on a website? That’s what GravityView does.

GravityView integrates with the popular Gravity Forms plugin and makes it easy to display entries on your website.

  • Embed Gravity Forms entry data in a post or a page
  • Control what data is displayed using a drag & drop interface
  • Moderate what entries are visible before they appear on your website
  • Allow users to edit the entries they created
  • …and more

If you’re using Gravity Forms, you’ll want GravityView.

Help test the Constant Contact API 3.0 plugin beta!

Almost ready.

It’s been a long haul for the new version of the Constant Contact for WordPress plugin. I started working on it before Constant Contact finalized their new API, so let’s just say it has been a major undertaking 🙂 Now I need help getting it ready for release!

The new Constant Contact WordPress plugin has some cool features, such as inline editing of lists and contacts, nicer report layouts, error/activity logging, and much cleaner ways of doing things.

Please help by installing the plugin and reporting issues.

You can download the latest build of the plugin here.

Please help test the plugin and — most important — report issues using this form.

I want to release the plugin in the next three weeks, so please download, install, and submit issues as soon as possible. It would be a huge help.

Are you a developer?

Please help out and contribute on GitHub. Your help will earn you a thank-you link on the plugin’s settings page!

Future plans

Once the new version is released, I plan on allowing this plugin be the connector to Constant Contact for my other integrations (Contact Form 7, Gravity Forms, and Fast Secure Contact Form). That way, other forms can be used instead of the Form Designer and you’d still get all the other functionality of the main API plugin, like viewing and editing contacts.

Thanks for your help!

How to remove WangGuard honeypot fields

WangGuard is a great plugin for blocking spam registrations. Without it, this site gets about 50 per day. No good!

I did encounter an issue, however: The <![if !IE]> tag was showing on my registration form for some reason. The code WangGuard adds inside the tag is used to generate a “honeypot” section: spam bots see the fake form fields but users don’t. Spam bots fill out the fields and when the form is submitted, WangGuard sees that the fake fields are filled in and knows the user is spam. The good news is that WangGuard still works without the honeypot fields.

Add the code below to your functions.php file to remove the honeypot fields:

 * Get rid of WangGuard's honeypot fields on the registration form
function kws_remove_wangguard_honeypots() {
    $i = 1;
    // WangGuard generates actions in a random position between 1 and 10, 
    // so we remove all actions that may exist.
    while($i < 11) {
        remove_action('register_form','wangguard_add_hfield_1' , $i);
        remove_action('register_form','wangguard_add_hfield_2' , $i);
        remove_action('register_form','wangguard_add_hfield_3' , $i);
        remove_action('register_form','wangguard_add_hfield_4' , $i);
add_action('plugins_loaded', 'kws_remove_wangguard_honeypots');

Gravity Forms Directory Security Update

Yesterday a crucial security flaw was discovered in the Gravity Forms Directory plugin and fixed immediately. Version was released and takes care of the issue. __Please update immediately__.

For the security of the users still running older versions, we can’t go into what the flaw was, but it had to do with viewing Gravity Form entries without permission, and was severe.

Gravity Forms Directory versions affected: 2.4.1 – Version fixes the problem

The flaw was discovered by Baruch Moskovits. We released a patch within one hour of the discovery.

How to get all downloads in Easy Digital Downloads

Easy Digital Downloads defaults to using 10 results per page when using the get_products() method. You can modify this default using the edd_api_results_per_page filter.

Here’s how to fetch all products at once:


// Force EDD to show all the downloads at once.
add_filter('edd_api_results_per_page', 'modify_edd_api_results_per_page' );

// Get all the EDD products
$products = $EDD_API->get_products();

// Restore sanity to EDD results per page.
remove_filter('edd_api_results_per_page', 'modify_edd_api_results_per_page' );

* Modify the number of results fetched by EDD
* @param int $per_page Previous results per page setting
* @return int New results per page setting. If you have this many, you're in trouble.
function results_per_page($per_page) {
return 99999999; // Yeah, you've got lots of products!

How to Add Support for Display Advertising Code in Google Analytics for WordPress

It’s really simple to use Google’s Display Advertising code, so I thought I’d share how.

To enable the new GA features:

  1. Check the “Show Advanced Settings”
  2. Under “Advanced Settings,” check the checkbox for “Host ga.js locally:”
  3. In the text field that appears, enter: //
    • Note: The missing http and https is intentional – if your site’s in secure mode, it will use https, otherwise http)
  4. Save your settings!

30 Years of Mac: White and Male

Apple has a deep-seated diversity problem.

Apple Diversity and GenderIn the 30 Years of Mac mini-site, a thoughtfully prepared homage to the history of the Macintosh and the people who use it to create, there were four women featured out of the twenty-eight profiles. One of the women featured, Noemi Trainor is an educator, a role women are “allowed” to be in. There were no Blacks or Hispanics represented.

There were four non-white males represented in 30 Years of Mac: a Korean, Japanese-American, Japanese, and Lebanese-American were profiled.

It’s easy to say that this has been gone over before. It’s well-known that Apple’s leadership is all white males (soon to include a women, Angela Ahrendts). Using, I can only find one woman in Apple’s leadership since 1997: Nancy R. Heinen. Nancy Heinen worked at Apple as Senior Vice President and General Counsel from September 1997 to May 2006, until she was sacrificed for backdating stock-options for Steve Jobs. No minorities.

Diversity with a Capital D

Board recruitment is not the problem, culture is.

In the next Apple shareholder meeting, Apple will vote to start to improve their board diversity. Their board charter will be updated to include the following statement:

The nominating committee is committed to actively seeking out highly qualified women and individuals from minority groups to include in the pool from which board nominees are chosen.

It’s obvious by looking at their leadership team and board roster that diversity is simply not a part of the Apple culture. This culture will not change with an improved board recruiting policy. Changing a culture is a much tougher nut to crack. On Sheryl Sandberg’s website, there’s a suite of tools for increasing organizational diversity through non-biased hiring and management practices. Creating a Level Playing Field, a brilliant talk by Stanford Professor Shelley Correll, would be a good place to start.

It’s gotten bad.

I’m mad at Apple. It’s inexcusable that one of the largest companies in the world, a trendsetting company, does not care more about diversity. Apple should be setting the example for the tech world and being a diversity leader. I’m tired of seeing high-resolution images of Bob Mansfield and Jonny Ive.

I’m aghast that the 30 Years of Mac website features mainly white dudes, apparently the only innovative users of Macs. Surely, Apple could have found some African American innovative graphic designers that used the Mac over the past 30 years and represented more than four women. Apple chose not to.

Who was the editor of 30 Years of Mac? Who looked at the featured profiles and said “This represents our users”? Did someone at Apple say “I think we should feature more minorities and women?” or “Gee, that list of people is really, really white”? If not, that voice needs to be heard, and if someone did say that, that voice needs to be louder.

It’s time for Apple to step up their game and change their culture.

[EDIT] – Apple has promoted Denise Young Smith, an African-American woman, to run HR. Here’s a snippet from the Bloomberg article:

Smith is the latest woman to join Apple’s top ranks, which also include Katie Cotton, vice president of communications, and Angela Ahrendts, the former Burberry Group Plc chief executive officer who will lead retail operations.

Gender and race is a touchy topic, and I’m trying to represent my point of view without being disrespectful. If I use any language the you find offensive, please let me know.

Set the Width for a Google Maps InfoWindow

Working with Google Maps v3 is way fun.

If you’re a masochist.

Infowindow width
Scrolling InfoWindow
It seems like there’s no easy way to set the width of an InfoWindow. You can set the minWidth parameter, but that does nothing.

If you have content that exceeds the InfoWindow window, you get this: a scrolling box. That’s terrible.

The solution is horribly easy.

Looking Through the InfoWindow
The solution presents itself.
This will solve all your problems, and make you wish you had the past two hours back of your life: use the provided .gm-style-iw class to style the InfoWindow content container.

/* Just use .gm-style-iw */
.gm-style-iw {
width: 300px; 
min-height: 150px;