Marking Posts as New in WordPress

I was updating my bookmarks page and wanted a way to indicate the stuff that I’d added recently, which led me to thinking about how to identify posts from a particular timeframe.

The Question

How can I mark recent posts based on a particular timeframe?

The Result

I considered a couple of options (listed below) and ended up with a fairly simple solution using relative time, something WordPress has built-in. On the front-end, it just adds a little clock icon next to the title of any resource added within the last 30 days:

new resource indicator

Potential Solutions

My first thought was that I could use PHP to check whether the post date was within a certain range.

1. Compare Year and Month

I was thinking maybe I’d check the post year against the current year, then if it matched I’d check against the current month. However, I dismissed that before I got past about 20 characters of code because I realized that it would throw off the time frame of the results depending on where in the month we are. Oh well, we all have bad ideas sometimes.

2. Date Calculations

Then I was thinking I’d use PHP to check the date against a relative time frame, e.g. the last 30 days. Something like the reverse of this Stack Overflow question and solution.

That would work, but then I remembered that WordPress has relative post date built in, where you can display the time as “1 day ago” or “30 minutes ago” using the function human_diff_time (function reference). Hooray, even better!

3. Using Relative Time

So then I was thinking, with that relative time I just need to check and see if we’re in the right time frames to be what I’d consider “recent.” The numerical values returned won’t be useful but the words are definitely useful. I double checked when the transition in words happens by looking at the core code underneath that function. I was able to confirm that anything with a relative time in minutes, hours or days has been posted in the last 30 days, and I’d consider that recent.

Full Solution

Here’s the full solution I ended up with (limited to just the template code within the loop, since the rest of the template is irrelevant to the question):

<?php while ( $the_query->have_posts() ) : $the_query->the_post(); ?>
    <?php
        $postdate = human_time_diff( get_the_time('U'), current_time('timestamp') ); // get the post date in relative time
        $recentvals = array('min','mins','hour','hours','day','days'); // the values I consider "recent"
    ?>                          
    <li class="filterable">
        <a href="<?php the_field('url'); ?>">
            <span class="project-title"><?php the_title(); ?><?php foreach ( $recentvals as $recentval ) : if ( strpos($postdate, $recentval) !== FALSE) : echo ' <i class="fa fa-clock-o"></i><span style="display:none;">new</span>'; endif; endforeach; ?></span>
        </a>
        <span class="small"><?php the_field('description'); ?></span>
    </li>
<?php endwhile; ?>

The Breakdown

Let’s take a closer look piece by piece at what this code does:

Set Variables

First up, there are two pieces of information I want to use in my comparison. That’s this part of the code:

<?php
        $postdate = human_time_diff( get_the_time('U'), current_time('timestamp') ); // get the post date in relative time
        $recentvals = array('min','mins','hour','hours','day','days'); // the values I consider "recent"
    ?>

There are two variables set up here:

  1. The post’s relative publication date, meaning how long ago it was posted in words (e.g. “20 mins” or “2 days”)
  2. The time frames I want to include as “recent,” using the words provided by that relative time function (options are: “mins,” “hours”, “days,” “weeks,” “months,” and “years” and the singular of each of those)

For the first, I just used WordPress’s built-in function, straight off the Codex page except I’m assigning it to a variable rather than echoing it (displaying it) on the page.

For the second, I have created an array of the words I’ll accept as “recent,” using both the singular and plural forms. I’m actually not sure if it’s possible to just use the singular and I don’t feel like testing it so I’ve just used both for safety’s sake.

Compare the Two

Next, I need to figure out whether the current post date for each post contains any of the words in my array. I referenced this thread on Stack Overflow for this code:

<?php 
foreach ( $recentvals as $recentval ) : 
    if ( strpos($postdate, $recentval) !== FALSE) : 
        echo ' <i class="fa fa-clock-o"></i><span style="display:none;">new</span>'; 
    endif; 
endforeach; 
?>

This runs through each of the allowed time frame words in my array and compares them against the post date. If one comes up as a match, it prints out the code in the echo line.

Show the Icon, Plus Search

The printed HTML from that snippet is:

<i class="fa fa-clock-o"></i><span style="display:none;">new</span>

That creates the Font Awesome clock icon along with a hidden span (I know, I know, lazy inline CSS). The hidden span is there so that it’s possible to use the in-page “search” function to pull up the new posts.

Implementation Keys

If you’re going to implement this yourself, the key things to remember are:

  1. The code needs to be within the loop, including the bit where you set the variables.
  2. You’ll need to determine which words constitute “recent” and update your array accordingly.
  3. You’ll likely also need to update your icon/ display HTML to fit your purposes (whether it’s just displaying text or adding in an image or another icon font or whatever).

Business & Web Development Summer Reading List

Summer Reading List
While the summertime means more time spent with my family, away from the computer, I’ve been trying to keep on top of my blog and article-ready. I just skim most things that cross my Twitter and RSS feeds, but the articles in my “to read” list are things that looked good enough at first glance that I want to hold on to them for a deeper read or for future reference. Here they are, split by the topic:

New Technology

Web development is constantly evolving, so a lot of my reading is to keep up with the new stuff coming out across the languages and technologies I use.

Accessibility

I’m eager to learn more about accessibility and to incorporate more best practices into the sites I build so I’ve been saving references right and left.

Specific Techniques

These articles cover techniques I haven’t used yet but want to for various projects/ concepts/ ideas.

Business

And last, but not least, I am constantly ruminating on business topics. These articles cover things I’m thinking about or want to learn more about:


I also share articles of interest to me on the regular over on Twitter. If you’ve got suggestions/ tips on great things you’ve read lately (or have on your to-read list), put ‘em in the comments!

Problem Solving Threaded Comments in Shopify Blogs

Problem Solving Threaded Comments in Shopify
I recently had a potential client ask for threaded comments (where replies are shown below the original comment) in a Shopify blog, which is not a feature the platform offers natively. It got me thinking about how we might be able to make it work.

I thought it’d be interesting to share the thought process I went through when approaching this problem, since one of the key components of a web developer’s job is tackling implementation problems like this but the actual problem solving is not something we talk about as much as we probably should.

The Problem

Shopify blog comments are a single level, with no reply hierarchy. WordPress does offer threaded comments, and it’s what many blogs use so that’s become a familiar feature. Beyond familiarity, threaded comments are excellent for building community and generating a real conversation with readers.

How can we get comment replies in Shopify to be visually linked to the original comment so as to show the conversation?

The Thought Process

The first set of questions that came up when I started thinking about this problem:

  • Is there a way to have a reply link on the comments like you’d see on WordPress so anyone can reply to any top level comment (we’re only aiming for one level of replies for now)?
  • If not, is there a way to have the site owner able to reply to comments, even if it isn’t something the general public is able to do?

A Potential HTML & jQuery End Model

My initial thought was that we could associate replies to the original comment in the thread using the comment id, which is something Shopify stores for each comment (accessed via the liquid tag {{ comment.id }}).

My thought was that if we put the parent comment ID in the markup for both the parent comment and any reply comments, we could then use jQuery to move the replies up just under the parent (using append() or something similar).

This would look something like this:

<div id="comment-1">
    I'm the parent comment.
</div>
<div id="comment-2">
    I'm an unrelated comment.
</div>
<div id="comment-3" class="comment-1">
    I'm a response to the first comment.
</div>
<div id="comment-4" class="comment-1">
    I'm another reply to the first comment.
</div>

With that structure, we could use jQuery to find all the comments with the class comment-1 and then move them after the comment with the matching ID.

Getting the Comment ID in the Markup

The problem now is that we’ve got to associate a different comment’s ID with the replies somehow. Some ways this could potentially work (depending on Shopify’s system constraints):

  1. We include a hidden field in the comment form that contains the parent ID (probably put there by jQuery when the reply link is clicked?) and that pushes that information to the comment object or to a metafield. Then we pull that out from the comment object in the class.
  2. Only the shop owner can submit replies, using the backend to write them and including the parent comment ID as a metafield on their comments. We use that metafield for the class.
  3. Only the shop owner can submit replies, including the parent comment ID in the body of their comment in a way that we can strip out and use in jQuery but that doesn’t look terrible if the jQuery fails for some reason (javascript off, future bug, etc.).
  4. The comment ID gets submitted in the body of the comment, put there somehow when the reply button is clicked, and in a way that we can strip it out and use it but it doesn’t look terrible if jQuery fails (maybe invisible or on submit).

That list makes it seems like those ideas all came up together, but really it was a little more linear. The first one was my ideal case, but was quickly shot down because the comment form can’t be modified to submit information that way (womp womp).

That led me to think about the second idea, since for a lot of content types in Shopify we can add custom metafields in the admin. Unfortunately, it seems as though metafields are not a thing for comments (womp womp again).

Those two dead ends lead me to the final two choices, where we’re submitting the values via the field we do have (which is pretty much just the comment content area). The fourth is likely preferable as it’s the most flexible and the most automated (less chance of things breaking), so that’s what we’ll be tackling.

Further Considerations

Did you read this far hoping for a solution? Sorry, I don’t have one for you yet. As of this writing we haven’t tackled the problem any further, but if/ when we do I’ll be sure to write it up.

For now here the things on my mind for the next phase of tackling this problem:

  • How do I put information from my parent content markup (the ID) into the comment textarea on a link click? (Here’s a Stack Overflow thread that may help)
  • What does that information in the textarea look like, if it’s even visible? How can I make sure it gets submitted without getting accidentally edited first?
  • How does that information get parsed in the printed comment so that it isn’t in the comment content and is in the markup.

Tips for Project/ Flat Rate Invoicing

Tips for Project or Flat Rate Invoicing
I recently had a question come my way from a new freelancer about pricing client work. She’d already created a draft invoice for the work and was looking for feedback on whether she was pricing appropriately and thinking comprehensively about the work.

While I didn’t provide her with feedback on her specific pricing, I did send some quick thoughts on the way she was itemizing the tasks and describing the scope of the project and thought they’d be worth sharing here for others who might have similar questions.

She had her invoice itemized out something like this:

Service Time Cost
Domain & Hosting Setup; WordPress Install* A hrs at $X/hour $YYY
Theme Research & Installation, Minor Customization B hrs at $X/hour $YYY
Content Entry (5+ Pages, Multiple Image Galleries) C hrs at $X/hour $YYY
*Cost of domain registration, hosting, and WordPress theme not included

The Good Stuff

There are a lot of good things about the way this is set up already!

Itemized Services

I was happy to see this person listing out various components of the service they’re providing the client, breaking things out into groups of similar tasks. This really helps clients understand what they’re paying for and also makes sure everyone is on the same page regarding project scope.

Research Time Included

It’s also great that she included research into themes as part of the project scope, since in this particular project she was helping the client find a suitable pre-made WordPress theme to use. It takes time to match up client requirements to available themes and that time should be accounted for and clearly delineated in the invoice or estimate.

License and Recurring Costs Not Included

I was also very happy to see that she had specifically noted that recurring costs (hosting, domain registration) and the cost of the theme are not included in the quoted total. I feel pretty strongly about not including those types of costs in base invoices and instead having the client have ownership over their accounts and pay the actual cost of whatever licenses are needed so that they have those things in their name.

I also usually note in my invoices that web font license costs aren’t included, as that’s another semi-hidden cost that the client should be aware of from the outset and that I won’t cover myself.

Areas for Improvement

While the info this freelancer included was a great start, there are also some definite areas for improvement and further specificity.

In fact, my general rule with estimates and invoices is to be as specific as possible and also to note that things that aren’t listed aren’t included. This helps protect me against scope creep and also makes sure the client knows they should ask early on in the process if they’re looking for something specific that isn’t listed on the estimate.

In this example, I had three suggestions for things to improve on.

Avoid Relative Terms

The phrase “minor customization” raised a big flag for me, as it’s unclear what “minor” would include. A lot of the time, things a client may think are “minor” actually aren’t as straightforward as they may seem, so it’s best not to use relative or subjective terms and instead be really clear about what you’re going to customize and what the limits are. I might specify “customization of colors, fonts, and header graphics” or something like that.

Include Hard Limits

I was also concerned by content uploading including “10+ pages” and “multiple” image galleries. This is another place where you want to be really specific and provide caps rather than minimums or general terms (“up to X pages” and “up to X galleries with up to X images each). Otherwise you are going to end up hating life when you’re uploading image 125 of 160 on your 15th gallery page.

Overage Plan

While I don’t actually include this in my estimates and invoices (it’s in my contract instead), I also prompted this freelancer to consider what she would do if she went over the hours she listed or if the client needed more than outlined in the project scope.

I don’t include hour indications in my estimates unless it’s a line item specifically for hourly work, as the hours are irrelevant to the client when I’m really quoting on a project or output basis. If I go over my predicted hours getting to the agreed-upon scope, that’s on me and it doesn’t change the quote for the client.

On the flip side, if the client ends up wanting more than what we agreed upon, it’s good to be clear about how you handle that. For me, I say that I’m ok with adding to scope but the client has to know that that increases the cost of the project and may also impact the time frame.


Overall, this freelancer was starting from a good place with her invoices and just needed a few small changes to make things more clear and concrete for both parties, which ensures a much smoother process overall.

Automating Theme Development Presentation at WordCamp Philly 2014

Over the weekend I got to speak at WordCamp Philly in the Developer Track, presenting on automating parts of the theme development workflow.

View on Speaker Deck

It was my first time speaking at a conference, much less giving a technical presentation (I’ve taught classes on technical topics but that’s pretty different than a conference presentation in front of a peer group). I was way more nervous than I expected (especially with some people I really admire in the WordPress world in the room), but I’m pretty happy with how it turned out!

I started out by debunking three reasons developers might have for not checking out some of the newer more automated development tools:

Herd behavior/ mind over machine

Too much too learn/ magic

I am an island/ No man is an island

Then I moved through a rundown of various things that can be automated and how you’d automate them broken up by rough phases of theme development.

theme development workflow phases

I covered a lot of tools in my 35 minutes, including Sass, Gulp, Autoprefixer, Yeoman, Git, Deploy and more.

Gulp styles task

Overview of a Gulp task to process Sass, prefix the CSS output, and minify

Demo of a Yeoman generator process for my Emi Starter Theme

Demo of a Yeoman generator process for my Emi Starter Theme

Initializing Git for a theme

Working with Git as part of a deploy process

There were a ton of other amazing sessions at the conference as well, and I believe they’ll all be up on WordPress.tv shortly if they aren’t already, so even if you weren’t around (or if you were but you missed a session) you can see them.

You can also check out my full slide deck if you’d like to check out the rest of the info that way.

Automating is about replacing grunt work with magic.

Thanks so much to WordCamp for having me!