Sponsor: WebdesignerNews – Curated Daily Web Design News

Go to Source

Design is hard enough without scouring hundreds of blogs, countless social media accounts, and thousands of design sites just to keep up with what’s changing. That’s why the team at Webdesigner Depot created WebdesignerNews, a one-stop site for the very latest industry developments.

WebdesignerNews covers a range of topics, from vanilla web design to code demos, from branding to brand new apps. If it matters to our industry, you’ll find it here. Even better, it is curated by humans. The team shortlists stories through social media response and then every single story is reviewed by industry experts. When you read WebdesignerNews, you can be confident that the stories you read are the ones that matter.

Direct Link to ArticlePermalink


Sponsor: WebdesignerNews – Curated Daily Web Design News is a post from CSS-Tricks

Go to Source

13 crazy freelancing myths debunked

Go to Source

A lot of designers have wild misconceptions about freelancing and what it’s actually like. Despite what many people think, it’s not all fun and games and working in your PJs.

At some point in their career, every designer is going to consider the possibility of going freelance. Before you make that decision, there are a few things you need to get straight…

1) You have total freedom

This is a big one. While it may be true that you have the freedom to live where you want, and you can work remotely, there are some restrictions: you have to work where there’s an Internet connection for example. In terms of creative freedom, it will be a long time before your business is successful enough to take on the projects you want. In the beginning, you’ll end up taking on any project that comes across your desk in order to keep the lights on and put food on the table.

2) You set your own schedule

This is rarely true. Some articles on the web have grossly exaggerated the freedom you have when working for yourself. You’ll have to have some sort of set schedule, so clients know when to contact you. Otherwise, they’ll contact you day and night, or they’ll expect you to work day and night. Another issue is consistency: clients want someone they know they can count on to be there, and not someone who flies by the seat of their pants.

3) You work whenever you want to

This definitely comes up as a big “nope.” Just like a regular day job, you’ll have deadlines you need to meet. If you don’t meet those deadlines, you may be paying for the damages out of your own pocket. Your clients will also expect projects to be completed in a reasonable timeframe; I just acquired a new business partner, due to the simple fact that his old partner would take 4-6 weeks to deliver a 5 page website.

4) You’ll work less

You couldn’t be more wrong on this one. Owning my own business, I’ve never worked harder in my life. You’ll be working late a lot to meet deadlines. You’ll also be working nights and weekends. Chances are that at times you’ll take on more work than you can normally handle, because you’ll be looking ahead at possible downtimes, due to seasonal activity.

5) You get to focus on what you like doing

While you do get to do what you love, you’ll also be doing everything else. You’re going to be the IT person, solving technical difficulties. You’ll also be the bookkeeper, because you’ll have to handle the accounting, budgeting, and paying the bills. You’ll also be the bill collector, chasing after people to pay you. You’ll be the office maintenance person, the janitor, and the secretary scheduling appointments with clients. You’ll even be the tea boy (or girl).

6) Work will come flowing in

It’s a common misconception that once you set up shop, you can just sit back and people will come pouring in looking for your services. While this is a nice thought, it’s merely a pleasant dream. It will take you a while to build a clientele. Simply building a portfolio online and hoping people show up there is wishful thinking.

You’ll have to be your biggest promoter, utilizing every strategy you can come up with to get the word out. You’ll need to learn social media skills, learn where you can advertise for free, and learn how to handle paid advertising that actually works. These same skills will be the ones you’ll be using to promote your clients’ businesses, so it’s a good idea to get good at them.

7) You’ll make more money

I’d love to say that the sky’s the limit when owning your own business. While it may be true that you have the potential to make as much as you want it will take some time to build. In your first year, you would be lucky to make what you made at your old day job. Don’t get discouraged. If you keep at it, you can eventually get where you want to be, but it’s not a get-rich-quick opportunity.

8) You’ll get to dress in your PJs every day

Not quite. At least, not if you want to actually succeed. You’re going to be meeting with clients, business owners, and business partners. People are actually going to want to meet you face to face before they hire you. You can’t throw away your suit and tie, or dress skirt. You’ll need those for presentations, and to look professional in meetings.

You only get to dress how you want when you’re in production mode at home. Even then, you may find yourself dressing up for work — a lot of freelancers find that changing outfits is a good way to shift mental gears between home-home and work-home.

9) You’ll have more free time

100% wrong. You’ll feel like you don’t have enough time. Between client meetings, bookkeeping, accounting, promoting, and everything else, you’ll be wondering when you’re actually supposed to sit down and do the design work. What’s worse is that even when there is a quiet period, you’ll be working harder to shorten that quiet period.

It can be a bit overwhelming at first; but as you get into the swing of things and develop your own system, that goes away.

10) You can sit in front of the computer all day and make money

It doesn’t work that way. You can work remotely, which is great, but you’d better have a ton of testimonials and portfolio work to show. Otherwise, you’re going to have to leave the comfort of your office to go to business events, meetups, and any other place where you may find work.

11) You’ll be able to land tons of work on freelancing sites

While some designers have found a lot of success from those sites, it didn’t happen overnight. Freelancing sites are full of wonderful opportunities to work for less than $1/hour, so if you want to do well your portfolio is going to have to be top-notch.

A lot of these sites require proficiency tests in order for you to promote your services in the first place. This can be time consuming, especially when you’re under the gun to pay bills. This can be something you work towards, but it should be on the backburner. It should be something you do during your downtime, and not your main focus.

12) You don’t have to work with people you don’t like

That’s definitely wishful thinking. You’ll work with people you like, don’t like, despise, hate, cherish, love, adore, admire, and more. You’ll work with just about anyone (or at least you’d better learn to) and you’ll be glad to do it. The flipside of the coin is that you’ll be more willing to do it, because all of the money’s going in your pocket. You aren’t working to make someone else wealthier.

13) Working from home is like working in paradise

This may be true if you’re single, live in a quiet neighborhood or apartment, and you have no pets. In reality, your stress level will go through the roof when working from home, especially if you have a spouse, kids, or pets. I started off working from home, and found I couldn’t concentrate. I was constantly interrupted, the kids needed to tiptoe (which never happened) and every neighbor in my area became barking dog owners all of a sudden.

Many freelancers are surprised how lonely they find the experience of working at home, especially at first, before you establish business connections of your own. Why do you think so many freelancers spend time in coffee shops? Because they’re productive work environments?

Working from home can also put stress on your relationships; and it can be difficult for those close to you to understand when you’re approachable and when you’re off limits. I eventually found an affordable office space, which was a lifesaver for my nerves, productivity, and my sanity.

Conclusion

Despite all of the freelancing myths out there, it can still be a rewarding experience. Working as a freelancer gives you the ability to control your career, potentially leading to the freedom that you’ve always wanted.

It can be tough when starting out, but if you hang in there, you’ll eventually develop your own system, giving you the potential to set your own work hours, determine your own income, and work with the companies you’ve always dreamt of. Understanding the difference between myths and reality will help you to set realistic goals, and to have realistic expectations for your freelance career.

 

Featured image, home office image via Shutterstock.

LAST DAY: 97% off Lifetime Certified Training in Adobe Software from Train Simple

Source
Go to Source

This Week in WordPress: Automattic Scoops Up WooCommerce

Go to source

This week’s round-up of WordPress news, views and reviews summarized in our daily email newsletter, The WhiP.

Subscribe to The Whip for daily lashings of WordPress goodness.

Subscribe to The WhiP


Crystal Ball – Newsletter #229

Joy to the World

(WordPress News)

BuddyPress 2.3.0 Beta 2 is now available. Just to recap, the upcoming version includes a new Attachments API, which will allow developers to more easily manage user-generated media. It’s also the long-awaited foundation for media-related BuddyPress components and features.

If you use cPanel’s one-click WordPress you may be using an outdated version of the CMS and missing out on important core update notifications.WP Tavern explains the situation and what cPanel is doing about it.

Developer Zoe Rooney talks about the joys of automating certain tasks in WordPress theme development in the latest edition of WP Engine’s Finely Tuned Consultant series.

Generation Z

(Opinion)

Here’s why testimonials can generate more selling power than the best sales copy.

WordPress vs Drupal vs Joomla. Guess which CMS comes out on top?

CalderaWP owner Josh Pollock waxes lyrical about plugin distribution on WordPress.org in a “new generation of WordPress.”

When you start a new project, what tools can’t you live without? Developer tom McFarlin lists his must-haves.

Search and Rescue

(Themes and Plugins)

Here are 12 great options for improving search on your site.

Beer Directory is a plugins for brewers and beer aficionados.

Elegant Themes reviews iContact Right, an email marketing plugin.

Beginner’s Luck

(Tutorials, Tips and Tricks)

A Beginner’s Guide To WordPress Website Maintenance (WP Explorer).

How To Disable Comments In WordPress (Pagely).

Quick Tips to Boost Your WordPress Website’s Speed (tuts+).

BuddyPress: The Lowdown on Loop Filtering (WebDevStudios).

Crystal Ball

(Off-Topic, Random Stuff)

Here’s a fun color game that will confuse you.

Will I ever finish building this website? Will my husband ever shave off his beard? For some of life’s biggest questions, the answers must surely come an eight ball that predicts the future via the medium of emojii.

Those are our links for today. We’ll be back on Tuesday after a short break – the emoji eight-ball in all its wisdom showed me a running man and an iPhone when I asked what my future holds. Somewhat apt.


No REST For the Wicked – Newsletter #230

WordCrab Cakes

(WordPress News)

“WordCrab is another example of one of Japan’s unique WordPress meetups. Members from all over from Japan gather in the Fukui prefecture, where they combine WordPress sessions with a giant crab party where everyone feasts upon the region’s renowned crabs.” Sarah Gooding from WP Tavern explores how Japan is shaping WordPress history.

On this week’s KitchensinkWP podcast, host Adam Silver talks about how to export a blog post and keep its HTML formatting.

And on the latest episode of WPwatercooler, the discussion centers on how to build a music website using WordPress.

Are you looking for work? Great! WebDevStudios and Maintainn are looking for front and backend developers, and a project manager. Meanwhile, WP Engine needs DevOps engineers.

The Medium is the Message

(Opinion)

Medium has made waves with the simplicity of its approach to content creation and the slickness of its execution. But what can WordPress learn from its example?

Please don’t hack core, especially to neuter core’s ability to upgrade itself.

“Onboarding starts with education. The Drupal community puts an emphasis on training at just about every event while only a handful of WordCamps offer a Foundation Friday or some other local onboarding event.” Here’s GoDaddy’s evangelist Mendel Kurland’s take on DrupalCon LA and what WordPress can learn from the Drupal community.

DreamHost has launched DreamPress 2, a shiny new take on managed WordPress hosting. Here’s WinningWP’s first impressions.

No REST for the Wicked

(Themes and Plugins)

WP REST API versions 1.2.2 and 2.0 Beta 1.1 are now available. These are critical security releases that address an issue where authenticated users were able to escalate their privileges bypassing the expected capabilities check.

The WP Contributions plugin lets you display your contributions to the WordPress project.

The Lasso front-end editing plugin for WordPress is now available on GitHub. Check it out, it’s cool.

GeoTargeting Pro WordPress lets you display location-specific content on your site.

Chip Off the Old Block

(Tutorials, Tips and Tricks)

WordPress Menu Pages and “Cheatin’ Uh?” (Tom McFarlin).

How to Detect AdBlock Users in WordPress (WP Beginner).

A Walkthrough on Conditional Tags in WordPress: 1 to 13 (tuts+).

Moving WordPress: Moving a Site Into a Multisite Network (tuts+).

How to Add Conditional Logic to Menus in WordPress (WP Beginner).

10 Best Tips and Tricks for Beginner Genesis Framework Users (BeginWP).

Disable Emojicons Introduced In WordPress 4.2 (Paul Underwood).

Say My Name, Say My Name

(Off-Topic, Random Stuff)

“There is something odd about this fetishization of teen talent and how far venture capitalists will go to get it, as well as how skeptical they can be of anyone over 25, given the fact that most billion-dollar startups today — Uber, WhatsApp, Slack — were founded by seasoned adults.” The story behind the real teens of Silicon Valley.

Have you ever wondered how people’s names differ around the world and how these differences might impact the design of online forms and databases? Well, now you know.

Lastly, here’s a hand-picked selection of the best Slack groups for all you procrastinators out there.

Those are our links for today. We’ll be back tomorrow with more terrible puns after we finish eating our crabs and adding new channels to Slack.

If you enjoy reading The WhiP, why not share the love and forward this edition to a deserving friend (or even an undeserving one!) and tell them tosign up here.


Woo-rdPress – Newsletter #231

Woo-rdPress

(WordPress News)

Big news! Automattic has bought out WooCommerce. Did you see it coming? Matt Mullenweg and WooThemes announced the acquisition on their respective blogs last night, and Matt also talks about the move in thefirst YouTube video uploaded to Automattic’s YouTube account. WP Tavern is reporting the deal “was in the range of $30 million,” which some are saying is a little low for an e-commerce platform that powers roughly 30% of all online stores. The acquisition is Automattic’s largest to date. Here’s more on the deal from TechCrunch and Mashable.

In other news, the Make WordPress Community team has put out a short survey about how to improve the tools available to WordCamp organizers.

WordPress Cape Town will host its second annual charity hackaton in June.

And Cloudways’ latest Q&A features themes developer Adam Mills who shares some good advice for those who want to start their career in WordPress.

Little Shop Of Horrors

(Opinion)

Shopify vs Magento vs WooCommerce vs Bigcommerce vs Wix – which eCommerce platform is the best? Unfortunately not WooCommerce, according to CodeInWP.

Here’s why blog comments still matter (perhaps) more than ever.

Elephant in the Boom

(Themes and Plugins)

BoomBar is a nifty plugin by the folks at iThemes that lets you to display targeted messages in notification bars at the top of your WordPress site.

Kanye Test

(Tutorials, Tips and Tricks)

How to Test Your WordPress Website for Responsive Design (Elegant Themes).

How to Sort Your WordPress Plugins into Groups (WP Beginner).

Create an App for Your WordPress Membership Site (AppPresser).

The Finer Points of “Posts” and “Pages” in a WordPress Context (WPShout).

Go Forth and Doodle!

(Off-Topic, Random Stuff)

Do you like to doodle? Google is looking for a new doodler.

Slack has gone and made a new podcast. (Spoiler: Adnan didn’t do it)

Those are our links for today. We’ll be back tomorrow with more Woo-rdPress news, views and reviews.

If you enjoy reading The WhiP, why not share the love and forward this edition to a deserving friend (or even an undeserving one!) and tell them tosign up here.


Continental Drift – Newsletter #232

Continental Drift

(WordPress News)

A few familiar faces (if you keeps tabs on the goings on in the WordPress community) have been announced as new core committers for WordPress 4.3: Ella Van Dorpe, Konstantin Obenland and Weston Ruter. Konstantin is also leading the charge on the upcoming release, which is due out on August 18.

“In striving to become a full-fledged CMS for advanced developers and large publications, WordPress has let itself drift away from its core philosophy of democratizing publishing by adding the very level of complexity it originally aimed to remove.” WordPress trainer Morten Rand-Hendriksen, who has taught and maintained the WordPress Essential Training course on Lynda.com for the past five years, shares his common pain points, roadblocks and advice for new users.

The Make WordPress Translation team is testing international theme and plugins directories.

Happy Joe, a non-profit organization that helps US veterans with entrepreneurship and employment opportunities using WordPress, haspartnered with WebDevStudios and SiteGround.

If you’re a developer keen to learn more about the WP REST API, you won’t want to miss Rachel Baker’s upcoming live event for WPSessions. Rachel is a lead engineer at The Wirecutter and one of the lead developers on the WP API project.

Baby WordPress Plugin

(Opinion)

So you want to build a career with WordPress, now what? Multisite expertRachel McCollin offers some advice based on her own experience.

“The phrase ‘It’s all in who you know’ usually means knowing powerful and influential people. In the WordPress community it usually means knowing as many people as possible. The larger your network of friends and associates, the more likely you are to get support.” So says HeroPress founder Topher DeRosia in his introduction to his site’s latest essay by Brazilian-based developer Rafael Ehlers.

The loneliness of the marketer or: how to promote a baby WordPress plugin.

Here’s a great guide to WordPress Squeeze pages.

And here’s a comprehensive guide to creating an ironclad WordPress development contract.

The folks at Codeable offer some tips on how to work effectively with WordPress experts.

Between You, Me and the Bed Post

(Themes and Plugins)

Postmatic, a plugin that “beautifully marries WordPress and Email together,” gets a thumbs up from The Matt Report’s, well, Matt.

Running on Empty

(Tutorials, Tips and Tricks)

How To Stop Saving Empty Values with the Settings API (Tom McFarlin).

Building An Advanced Notification System For WordPress (Smashing Magazine).

Using wp_remote_get() to parse JSON from remote APIs (Pippins Plugins).

How to Set Up GitHub (tuts+).

3 Simple WordPress Security Tips (Pagely).

Quick Guide to WordPress Custom Post Types Management and Filter Programming (Web Streaming).

Holier Than Thou

(Off-Topic, Random Stuff)

The super sarcastic guide to succeeding on social media.

Silicon Valley is a big fat lie, apparently.

Here’s yet another podcast to add to your playlist: The folks at Wired talk about Mad Max and recap GoT in the first ep.

Those are all our links for today. We’ll be spending the rest of the day tending to baby plugins and will be back with more tomorrow.

Related posts:

  1. This Week in WordPress: Automattic Acquihires and Big Web Host Survey Results This week’s round-up of WordPress news, views and reviews summarized…
  2. This Week in WordPress: FBI Warning to WP Sites, Top Caching Plugins Ranked This week’s round-up of WordPress news, views and reviews summarized…
  3. This Week in WordPress: NUX Team Announced, and Polyphasic Sleep This week’s round-up of WordPress news, views and reviews summarized…

Is the WordPress Community Supportive? My Journey into the Heart of WP

Go to source

WordPress is known as an open-source resource; a wonderful tool that can be put to good use to create any kind of website you can imagine. A major part of using it involves relying on the WordPress community at large.

These folks consistently work hard to develop and test new core features, perform bug fixes, and generally make sure the latest update or release is top-notch. The community is also available to developers who need a little help. The support forums are always bustling with activity, after all.

And while WordPress has this tremendous reputation as friendly to beginners and being consistently helpful, I had to wonder—how much of that is assumption or hype? Can the WordPress community really be as good as everyone says?

I decided to put those claims to the test. 

The Criteria

In order to see if the WordPress community really lived up to its reputation, I needed to come up with a plan. How would I test the community’s effectiveness as a resource? What would I do to gauge this across multiple sites? And what specific sites would I test?

So I first put together a list of criteria I would judge each community resource by. After some brainstorming, this is what I came up with. Each category is rated on a 1-10 scale (1 being the worst and 10 being the best):

  • Responsiveness – Did the community respond to my question? If so, how long did it take to receive a response?
  • Activity – Is the community very active? Did several people respond to my question or just one (or none at all)? Beyond my question, are the members consistently engaged in discussion?
  • Effectiveness – Were the responses useful? Did they help me solve the problem? Or did they just have me running around in circles?
  • Attitude – Were community members helpful, or did they at least try to be? Were they polite and friendly? Or did they make me feel out of place, unwanted, or even stupid?

With these criteria in hand, I approached the resources with an open mind.

The Test Subjects – and the Results

While there are many forums and blogs out there dedicated to WordPress, I wanted to keep things simple here and stick to those that WordPress users would gravitate to the most. I’ve included both WordPress-specific communities as well as social media communities to prove a fair assessment of how people who use WordPress interact with one another and support one another.

Twitter

Twitter is a broad social resource. People discuss every topic under the sun on this platform, which is why you have to use hashtags to get your queries seen by a relevant audience.

To test Twitter as a community resource, I asked a specific question of my followers. I used relevant hashtags like #wordpress and #webdesign:

twitter-question

I did receive at least one response to my question, which offered some insightful feedback. However, I ultimately didn’t get a solution to my problem and had to look elsewhere. In all honesty, this test doesn’t accurately portray the usefulness of Twitter (or the members of the WordPress community who are on it) very well. The number of responses I received had a lot to do with how many followers I have and how engaged I am with WordPress experts on this social site. Only those who previously followed me or who were searching the WordPress hashtag that day saw my posts. That’s a pretty limited audience.

Basically, Twitter can serve as a great WordPress resource if you’re already fully engaged with people there. If you have a large following and contribute to WordPress-related discussions on a regular basis, you’re much more likely to get something useful out of your interactions there than those who only post when they need help.

In terms of how Twitter functions as a part of the WordPress community, how did it fair?

  • Responsiveness: I posted my question at 1:24pm and received a response by 7:26pm. Not the best, but certainly not the worst, either. 7/10
  • Activity: Only one person responded to my question, but you can find a ton of discussion about WordPress on Twitter. 6/10
  • Effectiveness: Though the feedback I received was helpful and positive, it ultimately didn’t provide a clear solution. 6/10
  • Attitude: Can’t complain. All discourse was friendly and to-the-point. 10/10

Facebook

Facebook is about more than just posting pictures of your kids, especially when you dive into the world of Facebook groups. There’s a group for everything, it seems, and when it comes to WordPress, there are tons of groups out there to consider. Of course, some are better than others.

I targeted two groups that had a lot of members and activity and were recommended across several different blogs. I posted questions on each. My experience with these groups follows:

WordPress Help for Beginners

wp-beginners-help
The WordPress Help for Beginners group.

 

Since the question I posed to Twitter was a bit complex, I decided to dial it back a bit and ask a truly simple question here. After all, this group does promise help to beginners, so I needed to interact accordingly.

wp-beginners-help-question

At 5:47pm, I asked if anyone could recommend themes that’d be great for a site about comic books. My first response came in at 9:22pm. It didn’t offer any concrete suggestions, and rather said I could use plugins to get the comic book-specific features I needed with one of thousands of different themes.

Which is fair enough. But a theme suggestion or two might have been helpful here. Especially if I was a true blue beginner and didn’t want to fiddle with multiple plugins to build the site I wanted.

  • Responsiveness: It was fairly good. I received a response within 3 1/2 hours. Not fantastic but at least it was the same day and for a group with over 1,200 members, that’s not too shabby. 7/10
  • Activity: Hit and miss. There’s typically a question or two posted per day here, with several responses for each. There’s a good amount of discussion going on just not on a million different topics at once. 6/10
  • Effectiveness: Though the feedback I received wasn’t the most helpful in the world, the member did make a legitimate point. Also, responses to other questions are quite useful and explained in such a way that a total newbie could understand. 9/10
  • Attitude: Largely positive. I didn’t experience any snark and didn’t see any on other people’s posts. All in all, this is just a group of people who love WordPress and who want to help other people out. 9/10

Advanced WordPress

advanced-wordpress
The Advanced WordPress Facebook group.

 

The Advanced WordPress group is designed for those who have moved past the basics and actually develop sites for a living. Discussions center around code tips and tricks, troubleshooting, and more general questions about how to run a business. I asked the same question of this community as I did Twitter and the responses I got were pretty interesting. Although, this author tried to go back the day after posting to take a screen cap and the question had been removed altogether. Maybe my question was considered too basic? It’s not clear.

One person was very helpful and offered concrete advice—even linking me to a resource for further info. While he didn’t walk me through what I needed to do step-by-step, he did offer me a few more ideas of what to search for and included a link to the Google Custom Search Engine as a possible solution. He didn’t have a definitive answer for me, but it was definitely helpful advice.

Another individual questioned why I’d want to populate a page with search results for a preset query in the first place. Fair enough. But generally, when I see someone asking a question I assume they have a good reason to be doing what they’re doing.

  • Responsiveness: Lightning quick. I posted my question at 2:50 pm and received my first response by 3:07pm. Totally, completely impressed. 10/10
  • Activity: With over 14,000 members, this group is super active, not just with new posts and questions but with responses. Each new post gets tons of replies. 10/10
  • Effectiveness: I was offered useful advice that showed me a perspective I hadn’t yet considered. However, the lack of step-by-step instructions means I’d need to put in considerable legwork to get the answer I needed. 7/10
  • Attitude: For the most part, positive. However, there was an air of curtness with one reply. Perhaps I didn’t elaborate enough in my question. Perhaps it was too rudimentary for the audience. Still, being polite never hurt anybody. 7/10

WordPress.org Support Forums

WordPress Support Forums
The WordPress Support Forums.

I actually posted to the official support forums last. You’d think that would’ve been my first choice, but since I’d never posted there before, I opted to check out more familiar territory first, a la social media.

So, once I got to posting my question to the support forums, I’d learned from the experience of posting elsewhere.

That is, I’d honed the phrasing of my query. I’d already figured out what kind of questions elicit the best answers and what simply garners a snark-filled response. I’m telling you this, because it might just go to show that reworking your questions over and over again can sometimes improve the quality of help you get. Just some food for thought there.

wordpress-support-forum-question
I did my best to be as detailed as possible.

My experience with the WordPress.org forums began on the Hacks sub-forum. After mulling it over, that seemed to be the most appropriate spot for my question.

  • Responsiveness: I posted my question at 11am on a Monday and didn’t receive a response until Tuesday evening. While many other threads got immediate attention, mine wasn’t addressed right away. That’s okay though. It’s just the luck of the draw sometimes with these things. 6/10
  • Activity: Abundant! The official support forums are always bustling with activity. Which makes sense since they’re located right on WordPress.org. I only received one response but I’m not going to let that ding the forums’ score too badly here. 9/10
  • Effectiveness: The support forums as a whole are pretty dang effective. True blue experts post here all the time and collaborate on problem solving. Hot threads are particularly fun to watch as users troubleshoot together. Now regarding the effectiveness of the responses I received, I was a tad disappointed. The one response I got didn’t exactly address my question. Again, I might have just phrased it wrong or something, but I wasn’t really provided with a direct solution to the problem I had. 6/10
  • Attitude: Good for the most part. But don’t be caught posting a newbie question in the wrong place. Some folks are keen to jump all over you. Of course, the lack of patience makes sense when tons of people are posting in the wrong place or posting without searching the forum first on a daily basis. Occasional snark aside, the forums are friendly and helpful. People hang out here because they truly love WordPress. 7/10

The Verdict

I turn back to the question in the title of this post: Is the WordPress community any good? And my answer is this: Yes. Yes, it’s good.

People are passionate about this CMS, which means they love (LOVE!) to talk about it. And because they love to talk about it so much, communities develop around it to foster these discussions. Whether that’s on Twitter, a Facebook group, or even the official WordPress forums, it doesn’t matter. The discussions involve WordPress diehards who like to help out other people.

Will you run into the occasional person with an attitude or who seems to get a thrill out of making others feel inferior or dumb? Yes. But that’s true of any online community. There’s also going to be a sour apple in there somewhere. My advice? Don’t let them get to you. Rather, ask your questions*, review the feedback you receive, engage in the discussion, and thank those who took the time to help you out. Follow these instructions and you’ll reduce the likelihood of getting any flack from other developers and you’ll get the help you need.

*You should always Google your question and/or search the support forum for an answer to your question first. Failure to complete this step is a rookie mistake and will result in an (often quite curt) response that reads “There are tons of threads on this already,” or “You could easily find out how to do this by searching the web for it…” 

The aspects of the community I found to be the most helpful were the Facebook Groups. This might have just had something to do with the questions I was asking but the quickness of the responses and their quality were both head and shoulders above the other resources I put to the test. Obviously, I can’t speak for all WordPress Facebook groups here, but the two I used offered a largely positive experience.

Do you make use of the WordPress community? What has your experience been like? Did you find the help you needed or did you end up still having to figure it out for yourself? Please sound off in the comments.

Image source: Dennis Hamilton

Related posts:

  1. Five for the Future: How to Help Out in the WordPress Support Forums You probably remember the hullabaloo a few months ago around…
  2. Why WPMU DEV Has the BEST Support in the WordPress Community. Period. Tim Bowers, WPMU DEV’s head of support, likes to remind…
  3. New Plugin: Build Your Community with Private Messaging If building an engaged community where users can exchange ideas…

An Introduction to Vagrant

Go to Source

The following post is by Jason Witt, a regular around here on topics like WordPress development. This time Jason introduces us to a development prerequisite: the development environment itself. There are lots of ways to level up behind off-the-shelf app solutions, including scripting your own setups.

One question I hear again and again from new and experienced developers alike is “What local development setup do you use?” As a WordPress developer that needs, at a minimum, Apache, MySQL, and PHP, I would answer “You should give MAMP/XAMPP/WAMP a try, it’s easy to use and works great”. I still think that, but the more I learn and develop my skills as a developer, I no longer think MAMP/XAMPP/WAMP can support my needs.

Continua a leggere An Introduction to Vagrant

Animated Page Transition

Go to Source
animated-page-transition

A CSS powered animation, that replaces the refresh of the page while the content is updated using Ajax.

We’ve been playing around the idea of replacing the refresh of a web page with an animation, that takes place while the new page content is loaded using Ajax. We used the pushState method to manipulate the browser history.

Inspiration came from this beautiful website: jardins-poudriere.ch.

Creating the structure

The HTML structure is composed of a <main> element, wrapping the page content, a div.cd-cover-layer which is used to create the layer covering the content during the page transition, and a div.cd-loading-bar to create the loading bar animation.

<main>
	<div class="cd-index cd-main-content">
		<div>
			<h1>Page Transition</h1>
			<!-- your content here -->
		</div>
	</div>
</main>

<div class="cd-cover-layer"></div> <!-- this is the cover layer -->

<div class="cd-loading-bar"></div> <!-- this is the loading bar -->

Adding style

We used the body::before and body::after pseudo-elements to create the 2 blocks that cover the page content during the page transition: these elements are in fixed position, with height equal to 50vh and width equal to 100% of the viewport. By default, they are hidden outside the viewport using the CSS transform property (translateY(-100%)/translateY(100%)). When the user triggers a page transition, these elements are moved back into the viewport (using the .page-is-changing class added to the <body> element).

Here is a quick animation that shows the starting position of the body::before, body::after and the div.cd-loading-bar elements (gif created in After Effects):

page transition

body::after, body::before {
  /* these are the 2 half blocks which cover the content once the animation is triggered */
  height: 50vh;
  width: 100%;
  position: fixed;
  left: 0;
}
body::before {
  top: 0;
  transform: translateY(-100%);
}
body::after {
  bottom: 0;
  transform: translateY(100%);
}
body.page-is-changing::after, body.page-is-changing::before {
  transform: translateY(0);
}

The fade-out effect of the page content during the page transition is achieved animating the opacity of the div.cd-cover-layer. It covers the entire .cd-main-content element, has the same background-color, and its opacity is animated from 0 to 1 when the .page-is-changing class is assigned to the <body>.

The progress bar animation is created using the .cd-loading-bar::before pseudo-element: by default, it is scaled down (scaleX(0) and transform-origin: left center), while it is scaled back up when the page transition is triggered (scaleX(1)).

.cd-loading-bar {
  /* this is the loading bar - visible while switching from one page to the following one */
  position: fixed;
  height: 2px;
  width: 90%;
}
.cd-loading-bar::before {
  /* this is the progress bar inside the loading bar */
  position: absolute;
  left: 0;
  top: 0;
  height: 100%;
  width: 100%;
  transform: scaleX(0);
  transform-origin: left center;
}
.page-is-changing .cd-loading-bar::before {
  transform: scaleX(1);
}

Smooth animations are achieved using CSS Transitions. We have been using a different transition-delay value for each animated element in order to perform the different animations in the right order.

Events handling

We have been using the data-type="page-transition" to target the links triggering the action. When a click event is detected, the changePage() function is executed:

$('main').on('click', '[data-type="page-transition"]', function(event){
    event.preventDefault();
    //detect which page has been selected
    var newPage = $(this).attr('href');
    //if the page is not animating - trigger animation
    if( !isAnimating ) changePage(newPage, true);
});

This function triggers the page animation and loads the new content (loadNewContent() function):

function changePage(url, bool) {
    isAnimating = true;
    // trigger page animation
    $('body').addClass('page-is-changing');
    //...
    loadNewContent(url, bool);
    //...
}

When the new content is loaded, it replaces the old content inside the <main> element, the .page-is-changing class is removed from the body (to reverse the  page animation) and the new loaded page is added to the window.history (using the pushState() method).

function loadNewContent(url, bool) {
  	var newSectionName = 'cd-'+url.replace('.html', ''),
  		section = $('<div class="cd-main-content '+newSectionName+'"></div>');
  		
  	section.load(url+' .cd-main-content > *', function(event){
    	// load new content and replace <main> content with the new one
      	$('main').html(section);
      	//...
      	$('body').removeClass('page-is-changing');
      	//...

      	if(url != window.location){
        	//add the new page to the window.history
        	window.history.pushState({path: url},'',url);
      	}
	});
}

In order to trigger the same page animation when user clicks the browser back button, we listen for the popstate event, and execute the changePage() function when it is fired:

$(window).on('popstate', function() {
    var newPageArray = location.pathname.split('/'),
        //this is the url of the page to be loaded 
        newPage = newPageArray[newPageArray.length - 1];
    if( !isAnimating ) changePage(newPage);
});

You can read more about the popstate event and how browsers handle it here.

Note: we implemented a basic load() function to upload new content, but you may want to replace it with, for example, a $.ajax call in order to handle errors, etc.
Go to Source

Building An Advanced Notification System For WordPress

Go to Source

A lot of tools enable us to distribute a website’s content, but when we need to promptly reach a target group, an email notification system might be the best option. If your website is not frequently updated, you could notify all subscribers each time a post is published. However, if it’s updated frequently or it covers several topics, you could filter subscribers before mailing them.

If you opt for the latter, you could set up a user meta field that stores a bit of information to identify the subscribers to be notified. The same bit of information would label the posts you’re publishing. Depending on the website’s architecture, you could store the meta data in a category, a tag, a custom taxonomy or a custom field. In this article we’ll show you how to let your website’s subscribers decide when they want notifications, and linked to a particular location.

Can I Use A Plugin?

If WordPress is your CMS, you can choose from a number of plugins, such as the comprehensive JetPack1 or the more specialized Subscribe 22.

Subscribe 2 settings page3

Subscribe 2’s settings page. (View large version4)

Jetpack is easy to use, whereas Subscribe 2 is specialized and full-featured. Both plugins enable you to send email notifications to subscribers whenever a post is published. Unfortunately, neither allows you to notify specific users about specific content. And we want to select posts based on custom fields, mailing them to specific groups of users. Unfortunately, no plugin seems able to help us with this.

Things To Do

We are going to add several functionalities to WordPress’ core, and the CMS allows us to declare our own custom functions in the main file of a plugin. We’re not going to dive deep into plugin development, but you can get the information you need directly from the Codex5.

We have to accomplish the following tasks:

  1. add two meta fields to the user’s profile, the first of which stores the name of a location and the second of which determines whether the user will receive emails;
  2. add a custom meta box to the post-editing page containing the location-related custom field;
  3. select the users to be notified and send an email to them.

Add Meta Fields To User Profiles

WordPress stores user data in the wp_users and wp_usermeta tables.

WordPress database description

WordPress’ database description. (Image: Codex6)

Here, wp_users holds the list of all website users, while wp_usermeta contains all meta data associated with each user’s profile. Meta data is registered as key-value pairs in the meta_key and meta_value fields.

WordPress generates a bunch of meta data, such as nickname, first_name, last_name, description and wp_capabilities. Much of this data is automatically assigned to each user’s profile, and a user is able to edit it later from their profile page.

To perform our first task, we’ll add two meta fields to the profile pages of users. These fields will store the name of a geographic location and will allow the user to activate (or deactivate) the notification feature.

In the main file of the plugin, let’s define a global associative array whose elements consist of the names of US states:

$smashing_notification_states = array( 'AL' => 'Alabama', 'AK' => 'Alaska', 'AZ' => 'Arizona', 'AR' => 'Arkansas', 'CA' => 'California', 'CO' => 'Colorado', 'CT' => 'Connecticut', 'DE' => 'Delaware', 'FL' => 'Florida', 'GA' => 'Georgia', 'HI' => 'Hawaii', 'ID' => 'Idaho', 'IL' => 'Illinois', 'IN' => 'Indiana', 'IA' => 'Iowa', 'KS' => 'Kansas', 'KY' => 'Kentucky', 'LA' => 'Louisiana', 'ME' => 'Maine', 'MD' => 'Maryland', 'MA' => 'Massachusetts', 'MI' => 'Michigan', 'MN' => 'Minnesota', 'MS' => 'Mississippi', 'MO' => 'Missouri', 'MT' => 'Montana', 'NE' => 'Nebraska', 'NV' => 'Nevada', 'NH' => 'New Hampshire', 'NJ' => 'New Jersey', 'NM' => 'New Mexico', 'NY' => 'New York', 'NC' => 'North Carolina', 'ND' => 'North Dakota', 'OH' => 'Ohio', 'OK' => 'Oklahoma', 'OR' => 'Oregon', 'PA' => 'Pennsylvania', 'RI' => 'Rhode Island', 'SC' => 'South Carolina', 'SD' => 'South Dakota', 'TN' => 'Tennessee', 'TX' => 'Texas', 'UT' => 'Utah', 'VT' => 'Vermont', 'VA' => 'Virginia', 'WA' => 'Washington', 'WV' => 'West Virginia', 'WI' => 'Wisconsin', 'WY' => 'Wyoming' );

Thanks to this array, we will generate a select menu to avoid input errors by users. Now, we need to add two form fields to the user’s profile page. To do this, we will use two action hooks:

add_action( 'show_user_profile', 'smashing_show_user_meta_fields' );
add_action( 'edit_user_profile', 'smashing_show_user_meta_fields' );

Here, show_user_profile7 is triggered when a user is viewing their own profile, while edit_user_profile8 is triggered when a user is viewing another user’s profile.

The callback function prints the markup.

/**
 * Show custom user profile fields.
 *
 * @param obj $user The user object.
 */
function smashing_show_user_meta_fields( $user ) { 
    global $smashing_notification_states;
    ?>
    <h3><?php _e( 'Smashing profile information', 'smashing' ); ?></h3>
    <table class="form-table">
        <tr>
            <th scope="row"><?php _e( 'State', 'smashing' ); ?></th>
            <td>
                <label for="state">
                    <select name="state">
                        <option value="" <?php selected( get_user_meta( $user->ID, 'state', true ), "" ); ?>>Select</option>
                        <?php foreach ($smashing_notification_states as $key => $value) { ?>
                            <option value="<?php echo $key; ?>" <?php selected( esc_attr( get_user_meta( $user->ID, 'state', true ) ), $key ); ?>><?php echo $value; ?></option>
                        <?php } ?>
                    </select>
                    <?php _e( 'Select state', 'smashing' ); ?>
                </label>
            </td>
        </tr>
        <tr>
            <th scope="row"><?php _e( 'Notifications', 'smashing' ); ?></th>
            <td>
                <label for="notification">
                    <input id="notification" type="checkbox" name="notification" value="true" <?php checked( esc_attr( get_user_meta( $user->ID, 'notification', true ) ), 'true' ); ?> />
                    <?php _e( 'Subscribe to email notifications', 'smashing' ); ?>
                </label>
            </td>
        </tr>
    </table>
<?php }        

This table contains two custom meta fields. The first is a select menu whose options are generated by a foreach loop that iterates over the $smashing_notification_states global array. This way, the user doesn’t have to type the name of their state, but instead chooses it from a dropdown list.

As you can see, we’re calling the selected() function9 twice from inside two <option> tags; selected() is a WordPress function for comparing two strings. When the strings have the same value, the function prints selected='selected'; otherwise, it echoes an empty string.

The first time we call selected(), we’re comparing the current option’s value ('state') with an empty string (which means no state was selected). When iterating over the $smashing_notification_states array, we’re comparing the value of each element to the current value of the 'state' meta field. This way, we can automatically select the option corresponding to the existing 'state' value.

The second meta field to be added to users’ profiles is a checkbox. Its value will be 'true' or 'false' depending on whether the user chooses to receive notifications. Similar to selected(), checked()10 prints out the string checked='checked' when its two arguments have the same value. Of course, checked() applies to checkboxes and radio buttons.

Now that we’ve got the fields, we can save the user’s input. We need two action hooks to store the user data:

add_action( 'personal_options_update', 'smashing_save_user_meta_fields' );
add_action( 'edit_user_profile_update', 'smashing_save_user_meta_fields' );

Here, personal_options_update is triggered when the user is viewing their own profile page, while edit_user_profile_update is triggered when a user with sufficient privileges is viewing another user’s profile page. We have two hooks but just one callback:

/**
 * Store data in wp_usermeta table.
 *
 * @param int $user_id the user unique ID.
 */
function smashing_save_user_meta_fields( $user_id ) {

    if ( !current_user_can( 'edit_user', $user_id ) )
        return false;

    if( isset($_POST['state']) )
        update_user_meta( $user_id, 'state', sanitize_text_field( $_POST['state'] ) );

    if( !isset($_POST['notification']) ) 
        $_POST['notification'] = 'false';
    
    update_user_meta( $user_id, 'notification', sanitize_text_field( $_POST['notification'] ) );

}

This function verifies whether the user is allowed to edit_user, and if current_user_can is true, it checks the data and saves it in the wp_usermeta table.

Custom meta fields

The custom meta fields added to the user’s profile page.

Custom Meta Box And Custom Fields

We have to decide what kind of content should be included in the notification to subscribers. This decision will depend on your website’s architecture. In this example, we’ll go for regular posts, but you could choose a custom post type instead. The choice depends on your needs.

That being said, we are going to build a custom meta box containing a set of custom fields. These fields will be used to store an address, city, state and some other data related to location. Two other custom fields will enable and disable notifications on a per-post basis, and they will register the number of emails sent to users whenever a new post has been published. Let’s put another action hook to work:

add_action( 'add_meta_boxes', 'smashing_add_meta_box' );
function smashing_add_meta_box(){

    $screens = array( 'post' ); // possible values: 'post', 'page', 'dashboard', 'link', 'attachment', 'custom_post_type'

    foreach ($screens as $screen) {
        add_meta_box(
            'smashing_metabox',                     // $id - meta_box ID
            __( 'Venue information', 'smashing' ),  // $title - a title for the meta_box container
            'smashing_meta_box_callback',           // $callback - the callback that outputs the html for the meta_box
            $screen,                                // $post_type - where to show the meta_box. Possible values: 'post', 'page', 'dashboard', 'link', 'attachment', 'custom_post_type'
            'normal',                               // $context - possible values: 'normal', 'advanced', 'side'
            'high'                                  // $priority - possible values: 'high', 'core', 'default', 'low'
            );
        }
}

Here, add_meta_box11 accepts seven arguments: a unique ID for the meta box, a title, a callback function, a value for screen, the context (i.e. the part of the page where to show the meta box), and priority and callback arguments. Because we are not setting a value for the callback argument parameter, the $post object will be the only argument passed to smashing_meta_box_callback. Finally, let’s define the callback function to print out the meta box:

/*
 * Print the meta_box
 *
 * @param obj $post The object for the current post
 */
function smashing_meta_box_callback( $post ){
    global $smashing_notification_states;

    // Add a nonce field
    wp_nonce_field( 'smashing_meta_box', 'smashing_meta_box_nonce' );

    $address = esc_attr( get_post_meta( get_the_ID(), 'address', true ) );
    $city = esc_attr( get_post_meta( get_the_ID(), 'city', true ) );
    $state = esc_attr( get_post_meta( get_the_ID(), 'state', true ) );
    $zip = esc_attr( get_post_meta( get_the_ID(), 'zip', true ) );
    $phone = esc_attr( get_post_meta( get_the_ID(), 'phone', true ) );
    $website = esc_attr( get_post_meta( get_the_ID(), 'website', true ) );
    $disable = esc_attr( get_post_meta( get_the_ID(), 'disable', true ) );
    ?>
<table id="venue">
    <tbody>
        <tr>
            <td class="label"><?php _e( 'Address', 'smashing' ); ?></td>
            <td><input type="text" id="address" name="venue[address]" value="<?php echo $address; ?>" size="30" /></td>
        </tr>
        <tr>
            <td><?php _e( 'City', 'smashing' ); ?></td>
            <td><input type="text" id="city" name="venue[city]" value="<?php echo $city; ?>" size="30" /></td>
        </tr>
        <tr>
            <td><?php _e( 'State', 'smashing' ); ?></td>
            <td>
                <select name="venue[state]">
                    <option value="" <?php selected( $state, "" ); ?>>Select</option>
                    <?php foreach ($smashing_notification_states as $key => $value) { ?>
                        <option value="<?php echo $key; ?>" <?php selected( $state, $key ); ?>><?php echo $value; ?></option>
                    <?php } ?>
                </select>
            </td>
        </tr>
        <tr>
            <td><?php _e( 'Disable notification', 'smashing' ); ?></td>
            <td><input id="disable" type="checkbox" name="venue[disable]" value="true" <?php checked( $disable, 'true' ); ?> /></td>
        </tr>
    </tbody>
</table>
<?php
}

First, we’re initializing the global array and registering a nonce field12. We then add two simple text fields. The name attribute is set in the form of an array element, while the value is set to the corresponding custom field’s value. Finally, the main custom fields are added.

Just like with the user’s meta data, we add a select menu whose options are echoed, iterating over the elements in the $smashing_notification_states global array. Once we have built the select menu, let’s continue with a checkbox to enable and disable the single post notification.

Now we have to save the data: Our action hook is save_post. We’ll perform a number of tasks with the callback function. Take a look at the inline documentation for more information.

add_action( 'save_post', 'smashing_save_custom_fields' );

/*
 * Save the custom field values
 *
 * @param int $post_id the current post ID
 */
function smashing_save_custom_fields( $post_id ){

    // Check WP nonce
    if ( !isset( $_POST['smashing_meta_box_nonce'] ) || ! wp_verify_nonce( $_POST['smashing_meta_box_nonce'], 'smashing_meta_box' ) )
        return;

    // Return if this is an autosave
    if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE )
        return;

    // check the post_type and set the correspondig capability value
    $capability = ( isset( $_POST['post_type'] ) && 'page' == $_POST['post_type'] ) ? 'edit_page' : 'edit_post';

    // Return if the user lacks the required capability
    if ( !current_user_can( $capability, $post_id ) )
        return;

    if( !isset($_POST['venue']['disable']) ) 
        $_POST['venue']['disable'] = 'false';

    // validate custom field values
    $fields = ( isset( $_POST['venue'] ) ) ? (array) $_POST['venue'] : array();
    $fields = array_map( 'sanitize_text_field', $fields );

    foreach ($fields as $key => $value) {
        // store data
        update_post_meta( $post_id, $key, $value );
    }
}

Our custom meta box is up and running, and it looks like this:

Custom meta box13

The custom meta box showing the location details. (View large version14)

Building The Notification System

If you were working with custom post types, you would need the publish_{$post_type} hook (i.e. publish_recipes, publish_events, etc.). But since we are working with posts, publish_post is the hook for us:

add_action( 'publish_post', 'smashing_notify_new_post' );

/*
 * Notify users sending them an email
 *
 * @param int $post_ID the current post ID
 */
function smashing_notify_new_post( $post_ID ){
    global $smashing_notification_states;

    $url = get_permalink( $post_ID );
    $state = get_post_meta( $post_ID, 'state', true );

    if( 'true' == get_post_meta( $post_ID, 'disable', true ) )
        return;

    // build the meta query to retrieve subscribers
    $args = array(
            'meta_query' => array(
                    array( 'key' => 'state', 'value' => $state, 'compare' => '=' ),
                    array( 'key' => 'notification', 'value' => 'true', 'compare' => '=' )
                ),
            'fields' => array( 'display_name', 'user_email' )
        );
    // retrieve users to notify about the new post
    $users = get_users( $args );
    $num = 0;
    foreach ($users as $user) {

        $to = $user->display_name . ' <' . $user->user_email . '>';

        $subject = sprintf( __( 'Hei! We have news for you from %s', 'smashing' ), $smashing_notification_states[$state] );

        $message = sprintf( __( 'Hi %s!', 'smashing' ), $user->display_name ) . "\r\n" .
        sprintf( __( 'We have a new post from %s', 'smashing' ), $smashing_notification_states[$state] ) . "\r\n" .
        sprintf( __( 'Read more on %s', 'smashing' ), $url ) . '.' . "\r\n";   

        $headers[] = 'From: Yourname <you@yourdomain.com>';
        $headers[] = 'Reply-To: you@yourdomain.com';

        if( wp_mail( $to, $subject, $message, $headers ) )
            $num++;
    }
    // a hidden custom field
    update_post_meta( $post_ID, '_notified_users', $num );
    return $post_ID;
}

Once again, we declare the global array $smashing_notification_states. The two variables $url and $state will store the post’s permalink and state. The succeeding condition checks the value of the disable custom field: If it’s 'true', we exit the function. We have to retrieve from the database all users whose state meta field has the same value as the state custom field of the current post, and we use the get_users() function to accomplish this.

The wp_mail15 function accepts five arguments: recipient(s), subject, message, headers, attachments. The recipients could be passed as an array or as a comma-separated strings of addresses. So, we could have passed to the function all of the addresses together, but doing so would have made them publicly visible (this is the way wp_mail() works).

So, we’ll iterate over the $users array and call wp_mail repeatedly (which shouldn’t be done with a huge number of emails, as we’ll see in a moment). In case of success, wp_mail returns true. The counter is incremented by 1, and the loop continues with the next user.

When the foreach cycle ends, the current value of $num is registered in the hidden _notified_users custom field (notice the underscore preceding the name of the custom field).

Unfortunately, a loop iterating over and over hundreds of times could considerably slow down the script, as pointed out in the reference on the PHP mail() function16:

It is worth noting that the mail() function is not suitable for larger volumes of email in a loop. This function opens and closes an SMTP socket for each email, which is not very efficient.

For the sending of large amounts of email, see the » PEAR::Mail17, and » PEAR::Mail_Queue18 packages.

We could work around this, passing to the function the email addresses as BCCs, setting them in the headers19, as shown here:

function smashing_notify_new_post( $post_ID ){
    global $smashing_notification_states;

    $url = get_permalink( $post_ID );
    $state = get_post_meta( $post_ID, 'state', true );

    if( 'true' == get_post_meta( $post_ID, 'disable', true ) )
        return;

    // build the meta query to retrieve subscribers
    $args = array(
            'meta_query' => array(
                    array( 'key' => 'state', 'value' => $state, 'compare' => '=' ),
                    array( 'key' => 'notification', 'value' => 'true', 'compare' => '=' )
                ),
            'fields' => array( 'display_name', 'user_email' )
        );
    // retrieve users to notify about the new post
    $users = get_users( $args );

    $num = 0;

    $to = 'Yourname <you@yourdomain.com>';

    $subject = sprintf( __( 'Hei! We have news for you from %s', 'smashing' ), $smashing_notification_states[$state] );

    $message = __( 'Hi ', 'smashing' ) . "\r\n" .
        sprintf( __( 'We have a new post from %s', 'smashing' ), $smashing_notification_states[$state] ) . "\r\n" .
        sprintf( __( 'Read more on %s', 'smashing' ), $url ) . '.' . "\r\n";  

    $headers[] = 'From: Yourname <you@yourdomain.com>';
    $headers[] = 'Reply-To: you@yourdomain.com';

    foreach ($users as $user) {
        $headers[] = 'Bcc: ' . $user->user_email;
        $num++;
    }

    if( wp_mail( $to, $subject, $message, $headers ) )
        update_post_meta( $post_ID, '_notified_users', $num );
    
    return $post_ID;
}

As you can see, in case of wp_mail()’s success, we update the _notified_user custom field with $num’s value. However, in the code above, $num stores the number of retrieved users, not the number of times we call wp_mail().

Finally, if none of the solutions presented fit your needs, you could consider a third-party email notification system, such as MailChimp20 or FeedBurner21, which enable you to deliver notifications from a website’s feed.

A Note About Status Transitions

We hooked the smashing_notify_new_post callback to the publish_post action. This hook is triggered each time the status of an existing post is changed to publish. Unfortunately, publish_post is not fired when a new post is published. So, to send notifications, first save the post as “draft” (or “pending”). If you prefer to email subscribers each time a post is published, consider calling the save_post action instead:

add_action( 'save_post', 'smashing_notify_new_post' );
/*
 * Save the custom field values
 *
 * @param int $post_id the current post ID
 */
function smashing_notify_new_post( $post_ID ){
    global $smashing_notification_states;

    if( 'publish' != get_post_status( $post_ID ) )
        return;

    ...
}

Check the Codex for further information about status transitions22 and the save_post action hook23.

A Confirmation Message

When you work with the publish_post action hook, you will soon realize that testing your scripts can get a little tricky. When a new post is published, WordPress loads a script that saves data and, when it is done, redirects the user to the post-editing page. This double redirection does not allow variable values to be printed on the screen.

A confirmation message could be a good workaround. This solution allows us to check a variable’s values and to give the publisher useful information: specifically, the number of times wp_mail has been called (or the number of users to be notified).

Remember the $num variable? Its value was stored in a hidden custom field, _notified_users. Now we have to retrieve that value and print it out in a message using a filter hook.

Thanks to the post_updated_messages filter, we can customize WordPress confirmation messages and output them to the screen whenever a new post is saved or published (the Codex does not provide a reference for this filter hook, only an example of usage24). Here is the callback function we can use to customize the message when a post is published:

add_filter( 'post_updated_messages', 'smashing_updated_messages' );

/**
 * Post update messages.
 *
 * See /wp-admin/edit-form-advanced.php
 *
 * @param array $messages Existing post update messages.
 *
 * @return array Amended post update messages with new update messages.
 */
function smashing_updated_messages( $msgs ){

    $post = get_post();
    $post_type = get_post_type( $post );
    $post_type_object = get_post_type_object( $post_type );

    $num = get_post_meta( $post->ID, '_notified_users', true );

    if ( $post_type_object->publicly_queryable ) {
        $msgs[$post_type][6] .= ' - ' . $num . __( ' notifications sent.', 'smashing' );
    }
    return $msgs;
}
A custom message

When a post is published, a custom message is printed informing the author about the number of emails sent to users.

wp_mail Function And SMTP

WordPress’ wp_mail() function works the same way as PHP’s mail() function. Whether an email has been successfully sent will depend on php.ini’s settings, but most hosts include SMTP in their services. If you aren’t able to set that up, you could choose an external SMTP service and use it in tandem with the WP Mail SMTP25 plugin, which routes your emails through an SMTP service.

WP Mail SMTP configuration panel26

WP Mail SMTP’s settings page. (View large version27)

Be careful when you save data: the “from” field should have the same value as your account’s email address; otherwise, the server might respond with an error message.

Be aware that a plugin is not necessary: WordPress allows for the possibility of overwriting php.ini’s settings from within a script, with the phpmailer_init action hook. This hook allows us to pass our own parameters to the PHPMailer28 object. See the Codex for more information29 on this.

Designing Better Emails

Just like the PHP mail() function, wp_mail()’s default Content Type is text/plain. And just like the mail() function, wp_mail() allows us to set the Content Type to text/html. You can specify a different Content Type using the wp_mail_content_type filter or by setting the following headers:

$headers[] = "MIME-Version: 1.0";
$headers[] = "Content-Type: text/html; charset=ISO-8859-1";

Of course, a number of plugins allow you to manage your email’s Content Type from the administration panel. WP Better Emails30 is just one, but it’s one of the most appreciated. This plugin forces WordPress to send HTML emails, but it’s not its only feature. It also allows administrators to build their own email templates and to send arbitrary emails for testing purposes.

Finally, the following image shows what will be delivered to a Gmail user’s inbox.

Description of the image.31

The result in Gmail: The content has been generated by our code; SMTP parameters have been saved on WP Mail SMTP’s settings page; and the template is provided by WP Better Emails. (View large version32)

Conclusion

Our notification system is ready to be used. In building it, we’ve toured many of WordPress’ core features: user meta fields, custom meta boxes, custom queries, the mailing from script and more. If you’re interested, download the full code33 (ZIP file), and remember to switch each occurrence of the you@yourdomain.com string with your own email address.

You can expand on this a lot more. You could integrate this system with a third-party email management application such as MailChimp34 or Mad Mimi35. You could design flashy email templates. Or you could create even more personalized notifications.

Further Reading

(dp, al, ml)

Footnotes

  1. 1 http://jetpack.me/support/subscriptions/
  2. 2 https://wordpress.org/plugins/subscribe2/
  3. 3 http://www.smashingmagazine.com/wp-content/uploads/2015/04/subscribe2-large-preview-opt.png
  4. 4 http://www.smashingmagazine.com/wp-content/uploads/2015/04/subscribe2-large-preview-opt.png
  5. 5 http://codex.wordpress.org/Writing_a_Plugin
  6. 6 http://codex.wordpress.org/Database_Description
  7. 7 http://codex.wordpress.org/Plugin_API/Action_Reference/show_user_profile
  8. 8 http://codex.wordpress.org/Plugin_API/Action_Reference/edit_user_profile
  9. 9 http://codex.wordpress.org/Function_Reference/selected
  10. 10 http://codex.wordpress.org/Function_Reference/checked
  11. 11 http://codex.wordpress.org/Function_Reference/add_meta_box
  12. 12 http://codex.wordpress.org/WordPress_Nonces
  13. 13 http://www.smashingmagazine.com/wp-content/uploads/2015/04/venue-large-preview-opt.png
  14. 14 http://www.smashingmagazine.com/wp-content/uploads/2015/04/venue-large-preview-opt.png
  15. 15 http://codex.wordpress.org/Function_Reference/wp_mail
  16. 16 http://php.net/manual/it/function.mail.php
  17. 17 http://pear.php.net/package/Mail
  18. 18 http://pear.php.net/package/Mail_Queue
  19. 19 http://codex.wordpress.org/Function_Reference/wp_mail#Using_.24headers_To_Set_.22From:.22.2C_.22Cc:.22_and_.22Bcc:.22_Parameters
  20. 20 http://kb.mailchimp.com/campaigns/rss-in-campaigns/create-an-rss-driven-campaign
  21. 21 https://support.google.com/feedburner/answer/78982?hl=en
  22. 22 http://codex.wordpress.org/Post_Status_Transitions
  23. 23 https://codex.wordpress.org/Plugin_API/Action_Reference/save_post
  24. 24 http://codex.wordpress.org/Function_Reference/register_post_type#Example
  25. 25 https://wordpress.org/plugins/wp-mail-smtp/
  26. 26 http://www.smashingmagazine.com/wp-content/uploads/2015/04/wp_email_smtp-large-opt.png
  27. 27 http://www.smashingmagazine.com/wp-content/uploads/2015/04/wp_email_smtp-large-opt.png
  28. 28 http://phpmailer.worxware.com/
  29. 29 https://codex.wordpress.org/Plugin_API/Action_Reference/phpmailer_init
  30. 30 https://wordpress.org/plugins/wp-better-emails/
  31. 31 http://www.smashingmagazine.com/wp-content/uploads/2015/04/better_email-large-preview-opt.png
  32. 32 http://www.smashingmagazine.com/wp-content/uploads/2015/04/better_email-large-preview-opt.png
  33. 33 http://provide.smashingmagazine.com/sm-email-notification.zip
  34. 34 http://mailchimp.com/
  35. 35 https://madmimi.com/
  36. 36 http://www.smashingmagazine.com/2011/10/25/create-perfect-emails-wordpress-website/
  37. 37 http://codex.wordpress.org/Post_Status_Transitions
  38. 38 http://codex.wordpress.org/Plugin_API/Action_Reference
  39. 39 http://codex.wordpress.org/Plugin_API/Filter_Reference
  40. 40 http://codex.wordpress.org/Custom_Fields
  41. 41 https://developer.wordpress.org/plugins/metadata/creating-custom-meta-boxes/
  42. 42 http://codex.wordpress.org/Validating_Sanitizing_and_Escaping_User_Data
  43. 43 https://codex.wordpress.org/Data_Validation

The post Building An Advanced Notification System For WordPress appeared first on Smashing Magazine.

Go to Source