Don’t Give ThemeForest Any Reason To Reject You

Marko Prelec
Jan 26, 2016 · 7 min read

Few months of hard work and your brand new, “the most awesome WordPress theme yet” is ready for ThemeForest. The only thing left is Envato’s blessing that your theme meets their standards. Well. We all know how this usually ends. With an email saying Your theme is not quite ready yet. Sounds familiar?

Image for post
Image for post

At ProteusThemes, we currently have 13 approved WordPress themes on ThemeForest marketplace. Many of them were rejected at least once. With each reject over the last three years we learned many things about the review process. We want to save you some gray hair with this list of rejections we have received so far. Here is the list, I will explain how we coped with them afterwards.

Frontend soft rejections

We can see a lot of small mistakes here which will get your theme soft rejected. Most of those issues can be spotted using the following little tricks. Add Monster Widget in all your themes widget areas and check if everything looks perfect.

Import WordPress dummy data for testing all the post and page variations. In the import you will also find some different menus for your menu areas. There are plenty of edge cases which can be easily overlooked. Make sure all the edge cases look good and you will also save yourself a lot of time from support once your theme is approved.

At the end, give another look at your site in all major browsers and all devices you can get your hands on. Lastly, check if your code passes W3 validator. If it does, your theme is good to go.

Backend soft rejections

  • Code line endings. Related screenshot
  • This is not allowed. Related screenshot
  • Prefix all your custom functions, variables, classes, etc. A good rule of thumb is to prefix everything with your theme initials and your own initials. Read more: Related article
  • Use pagination functions. Remove hidden folders/files . Missing comment-reply. Related screenshot
  • Please do not use any deprecated tags. Use theme check plugin to test for this and other issues. Related screenshot
  • Don’t use CDN to include CSS or JS. Related screenshot
  • The WordPress theme should make use of the following inbuilt functions to validate or sanitize content on input or escape any questionable content for put. Related article, related article eg: Related screenshot please check every output.
  • .jshintrc .bower.json .gitignore Hidden Files or Folders found.
  • Custom Post Types are plugin territory. Related article
  • Custom widget areas must use the safety condition “is_active_sidebar” to ensure no naming conflict with other plugins.
  • Theme directory path is missing require `vendor/autoload.php`; please load via get_template_directory()
  • Include files via get_template_directory() and not with locate_template because you’re not loading WordPress templates and core is very specific when it comes what is loading.
  • Using `wp_register_*` is only for scripts/styles that you know theme does not use by default, for the rest use `wp_enqueue_*` instead.
  • Please escape all translations with:
    `__( ‘Some String’, ‘text-domain’ );` `_e( ‘Some string’, ‘text-domain’ );`. When there is no HTML use: `esc_html__( ‘Some String’, ‘text-domain’ );` `esc_html_e( ‘Some String’, ‘text-domain’ );`
    For some HTML: `wp_kses( __( ‘Some String something’, ‘text-domain’ ), $allowed_html_array );`. Related article
  • All dynamic data must be correctly escaped for the context where it is rendered. Related article
  • Always use esc_url when sanitizing URLs, including WordPress related, also, all home_url() must include a trailing slash such as home_url(‘/‘) See: Related article
  • Theme uses `eval()` please remove.
  • Remove this: Related screenshot
  • curl_init, curl_exec, fwrite, fopen, fread, file_put_contents, file_get_contents is not safe, use WP_Filesystem instead.
  • the extra brackets are not needed. Related screenshot
  • Don’t leave unused code fragments as comments in the code. Please check all your files. eg: Related screenshot
  • Directory path should be get_template_directory() and not dirname( FILE ).
  • Resource: Related article
  • All strings within PHP variables must be translated and escaped. At the same time, all functions must also be prefixed.
  • Use an appropriate directory paths when including files:
    — get_template_directory(); Returns the absolute template directory path,
    — get_template_directory_uri(); Returns the template directory URI,
    — get_stylesheet_directory(); Returns the absolute stylesheet directory path,
    — get_stylesheet_directory_uri(); Returns the stylesheet directory URI. See: Related article, related screenshot, related screenshot
  • Plugins are not being included properly. Related screenshot. Codex is outdated. See: Related article
  • Scripts/Styles are not properly prefixed. Related article
  • Install and run Theme Check plugin to go over the issues listed here: Related screenshot
  • Theme Description is insufficient. Related screenshot
  • Please disable force_activation (in TGMPA)
  • Third party scripts/ styles don’t need to be prefixed to avoid double loading. ref: Related code
  • Directory path should be get_template_directory() and not dirname( FILE ) (in PHP Composer).

The majority of these issues can be avoided, if you run theme check plugin, before you submit your theme to the TF review. Once you fix all the things that this plugin is warning you about, you will drastically improve your chances with the TF review. Of course this will not guarantee your theme to be accepted in the first go, but you will be on a good path.

One of the problems that we can outline is the dynamic data escaping, as you can see on the list above you should always use esc_html, esc_attr, esc_url,… on all of your output variables and even on your translations. A quick and easy search for `echo $` will find variables that you forgot to properly escape.

You should include the files with proper functions. Use “locate_template” function to include theme template files and “get_template_directory” for all other files (or “get_stylesheet_directory”, if you want that the child theme can overwrite these files). Never use the “dirname” function in your theme, that’s why other functions are available. But a problem appears, when you are using 3rd party libraries and other tools, that are using “dirname”, “eval”, “fwrite”, “curl_*” and similar functions, that TF does not approve of. Example: we are using Composer to include a few packages into our theme and Composer itself is using dirname… We were able to explain the problem to TF and they approved our theme (so you can also reason with TF review team :) ).

There were also some rejection items that we did not agree with TF, but they wouldn’t listen to us and we had to fix them anyway. For example: they always said “prefix everything!” which is definitely a good thing, but not “everything”. Why would you prefix 3rd party scripts or styles? They are not unique to your theme. But in our latest soft reject they told us “Third party scripts/ styles don’t need to be prefixed to avoid double loading”, so things are also changing in the right direction.

We would also recommend that you use the PHP_CodeSniffer with WordPress standards, which will tell you, if your code is up to WordPress standards.

Update: Apr 12th, 2016

we received yet another soft reject. This time it was for our new Auto theme. The issue was that we forgot to properly escape translation strings. Instead of just using regular gettext functions like `__()`, `_e()` and `_x()`, we now have to use the “escaped” versions of these functions like `esc_html__()`, `esc_html_e()`,… More information about this issue can be found in the official soft reject message below:

  • All theme text strings are to be translatable and properly escaped. Related article

If you resolve all of our soft rejects before uploading theme on ThemeForest, you are on very good way to get your item approved.

Let us know if our list helped you and share your experience with the ThemeForest review process.

Update: Sept 15th, 2016

Since the last update we released two new themes: Bolts and Shaka. And yes, we got some new soft rejects as well :)

  • Inconsistent prefixing: Related screenshot
  • Button not styled: Related screenshot
  • You should avoid and not to hardcode custom body_class(). Main reason for this is being able to remove the class when needed i.e. child themes. Related code, related article
  • Remove 2009: Related screenshot. This is just a dummy text, that can be changed in the customizer, but sure, we’ll remove the “2009”.
  • All theme text strings are to be translatable and properly escaped : Related screenshot. They found this string in the TGMPA options array, where you specify the required/recommended plugins. This is the name of a plugin and it should not be translated. We told them that and they accepted our explanation.
  • This is plugin territory : Related screenshot. Yup, they want you to use/create a new plugin (if you do not have a “utility” plugin already), for just one line of code. We couldn’t believe it. This line of code just enables the text widgets to display shortcodes.
  • No Gravatars: Related screenshot. I guess comments cannot exists without gravatars.

This article will be updated with new soft rejections we encounter in the future, so bookmark it and keep coming back. Meanwhile, take a look at our portfolio at ProteusThemes.

Backend part and both updates of the article was written by Grega Capuder.

Last update: Sept 15th, 2016

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch

Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore

Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store