CAll Us: +1 888-999-8231 Submit Ticket

Understanding WordPress Unit Testing Jargon

In our last post, we took a basic look at testing your code in WordPress. Today, we’re going to take another step towards writing well-tested code, by introducing you to (and helping you understand) all the jargon that gets thrown around when you talk about unit testing for WordPress.

Types of Tests

Yup, unit tests are not the only types of tests we can have for our application so let’s look at the different types of tests you may use in your work.

Unit Tests

These types of tests are the first stage in a testing system. They specifically test to ensure that the code you wrote performs as expected. Unit tests form the foundation of your tests because if your code doesn’t work properly, then later types of tests are built on a shaky foundation.

If I wanted to limit the editing of permalinks to site administrators for posts that are over two weeks old my unit test would use WP_Mock to ensure that I have a user of the proper type and a post with the proper date. Then I’d make sure that my function returned the expected true or false value.

Unit tests should have no dependencies outside of the code you’ve written. They should interact with no other system. That means our last post wasn’t a true unit test, it was an integration test because we interacted with the database as we created our user.

When you use unit tests as the foundation of your work, you help ensure that each method/function has a single responsibility because it gets progressively harder to test as you add more conditions to a single function.

Some of the tools you’ll encounter in unit testing WordPress projects are:

Integration Tests

This is the second type of testing you’ll do in your work. Integration tests make sure that the interactions between two systems function as expected. Unlike unit tests, the goal here is to see the interaction between multiple systems.

WordPress itself does more integration tests than unit tests because when most of the application was written best practices were different. The functions inside WordPress are much larger than many newer PHP CMS’s and do much more work. These bigger functions are hard to unit test properly because they do so much. That means we rely more on integration testing as we check how our code directly works with WordPress.

None of this is bad, it’s simply a product of an application that wasn’t built when testing was as common as it is now.

Another example of an integration test would be if you were building an integration with an email marketing platform. You may use unit tests to make sure you validate the email properly, and submit the form as expected. Integration tests would be used to ensure that when you submit your valid email to the email platform you deal with the response properly.

Tools for integration testing:

Mutation Testing

Mutation testing is only going to be used for projects that have some sort of test coverage already. This type of testing creates “mutants” of your code by introducing common coding errors. The goal is that your unit tests break when these errors are introduced which means you’ve caught and killed the mutant. Mutation testing tools will report back on how many mutants you’ve killed and the places in which you haven’t caught mutants.

Mutation testing can be used to measure the quality of your test coverage. If you’ve got lots of mutants alongside 100% testing coverage, you have a big problem. This means that your tests don’t catch common errors programmers make. You’ve got code breakage waiting to happen.

Essentially, you’re testing your tests.

Tools for mutation testing:

Acceptance Tests

These can also be called functional test or browser testing. Where unit tests start with your code and work outwards, acceptance tests take the view of the person using your software. With acceptance tests, you may automate the web browser to interact with your site to make sure that users see what they expect to see.

Acceptance tests are harder to maintain because a small wording change in the UI of your software can mean that the test breaks because the automation can no longer find the UI elements it expects to find. For that reason, only invest in acceptance tests for business-critical infrastructure, like the checkout process on your shopping cart.

Tools for acceptance testing:


Now that we’ve covered the types of tests you can do, we need to make sure we understand the other language that developers will use as they write tests.

Test Doubles

The term test doubles is a generic term that refers to any time you replace a production object/function/thing for testing purposes. We did this in our previous post on Getting Started with Unit Testing in WordPress when we used WP_UnitTestCase to add a user that didn’t exist in our production database. It can be helpful to think of it like a stunt double who “stands in” for the actor when things get dangerous. Test doubles “stand-in” for our data and code to make testing easier. They should look and behave like their production counterparts but be simplified to reduce complexity when we’re testing.


Mocks are used when you don’t want to interact with the API or database. You use a mock to fake database interactions so you can test a single unit of code without adding the complexity of a database.

A mock doesn’t have to be data in a database. A tool like WP_Mock has the ability to fake the hook system inside WordPress. This lets you test to see if a hook was called in your function, without needing to interact with WordPress itself.

Below we can see an example in WP_Mock where we fake the get_permalink function. We provide the number of times we expect the function to be called, arguments we expect, and the value we expect returned.

WPMock::userFunction( 'getpermalink', array(

  'args' => 42,

  'times' => 1,

  'return' => 'https://theanswertoeverything.fourtytwo/guide

We’ll cover how to use WP_Mock in a future post.


Stubs are hard coded values for our tests, like canned answers to the questions our test may ask. You would be using a stub if you instructed your test to assume that a user is logged in while running a test. Another test may assume that the user is logged out. Both tests would be making sure that your functions returned the proper values for the given branch in your code.

It’s very likely that you’re using stubs and mocks together. In the example above, you use a stub to assume the logged in value, and then a mock to make sure that the proper values are returned.


Test dummies are used when you don’t care about what the code does. Maybe you use a dummy to fill in an array or parameter list so that the code works properly. Stubs are extra information that likely doesn’t matter in the context of the specific test you’re writing.

For a logged-in user, maybe part of the function your testing expects a name. Even if your current test doesn’t need that name, you need to make sure it’s filled in so that your test passes. Of course, you should also test the result of your function without that name so you’re sure that you handle failure conditions properly.


A factory is a tool that lets us populate valid objects in our data model so that we can test the data. In our last case we used a factory when we added a user to our code inside WP_UnitTestCase.

One thing to be wary of here is changing the data model in your code. If your user suddenly needs an extra field, then you’ll need to head into every test and make sure that you have added that extra field every time you’ve used a factory.

Monkey Patch

This is a catch-all term for dynamically replacing attributes and functions at runtime. WP_Mock is “monkey patching” by replacing the default WordPress functions for testing. This means that we don’t have to call into WordPress directly when we’re unit testing.


An assertion is a boolean value which will be true unless there is an error. An example would be using assertFileEquals to check if a file has the expected content. It will return true if the file matches expectations, and you have a passing test.


Now, what overall system are you going to approach your tests with? Does it matter more that individual functions are valid, or that the behavior the end-user sees is valid?


TDD or Test Driven Development is when you write tests to validate that the code functions as expected. Like unit tests, you’re starting with the expectation of the code and then working towards the customer/user as you go. TDD doesn’t care about the outputs, it’s only concerned that the tests function as expected.

Tests written under TDD are only going to be readable by developers that understand testing and what an assertion means.


BDD or Behavior Driven Development grew out of the shortcomings of TDD. Here you start with what the end-user expects to happen as a result of the code. You still write your tests first, but you focus them on the result of your code. BDD doesn’t care how you arrive at outputs, as long as the expected behavior is the result.

One big benefit to BDD tools like Cucumber is that the language used to write the test is easily readable by customers and developers. It’s easy enough to understand that customers can write feature requests using Cucumber after a brief introduction.

Now, which one should you use? The correct answer is probably a bit of both. TDD methods can be used to ensure that the code the developer writes runs as expected. BDD can be used to make sure that the output of that code is what the customer expects to happen.

That’s all, folks! Understanding unit testing for WordPress just got a lot easier. With all that jargon under your belt, you’ll be ready for the next post where we’ll build a plugin using TDD and BDD with all the tools at our disposal.

Source link

What Is a Platform As a Service (PaaS)?

Once upon a time, software as a service was the only as a service acronym floating around. As the industry flourished though, forks came off of it into relating spaces to create a whole slew of aaS companies in numerous technological categories.

One of those forks is PaaS.

PaaS stands for platform as a service. It’s a service that provides and maintains a platform for developing, testing, and deploying applications for developers. All of the back-end infrastructure is managed by the PaaS, so that the developers can focus on their projects.

PaaS providers are able to reduce the amount of coding you need to do by providing you with middleware to use directly on the platform, with no dependencies on operating system compatibility (aw, yis).

A PaaS makes sense to use when you have multiple developers working on the same project. Like any other team-based SaaS app, PaaS apps allow you to add multiple users in a web-based development environment to co-work remotely on the same project.

Similar to more infrastructure-focused service providers like Hostdedi, PaaS providers include the basic infrastructure required to deploy apps, such as servers, networking, storage, and reference architectures. 

However, PaaS is arguably a more complete solution for app developers, providing an environment which allows you to build, collaborate, test, deploy, and manage your applications, all in one place.

You may not be familiar with the term PaaS, but if you’re a developer, you may already be using one:

  • Beanstalk
  • Heroku
  • Microsoft Azure

Platform as a service companies do one thing: save app developers time and money by bundling and automating a bunch of the things they’re used to doing manually. Then, when you run into problems, there’s a team of experts just behind the curtain to help you out.

PaaS companies are to app developers what Hostdedi is to ecommerce site developers – an all-in-one solution with a team of experts who specialize in your field. You don’t need tier one support at this stage in the game, you need someone who’s at least as informed as you are to help solve these problems.

Check out the PaaS providers above to help build your next application, and when it’s time to launch, talk to Hostdedi about managing your ecommerce site.

Choose From multiple Managed Applications

Source link

What Is PCI Compliance? – Hostdedi Blog

When it comes to processing payments online these days, most people don’t even bat an eye. Shoppers are paying with credit cards, over email, and through Facebook, but for ecommerce sites, payment security risk aversion is integral to how they do business.

Here’s how to make sure that your clients’ sites are staying compliant, and what to do when you’re dealing with an out of date application that’s reached end-of-life.

What does it mean?

First of all, let’s get our heads around what PCI compliance even means.

Originally set by the major credit card companies, the PCI Security Standards Council formed these parameters for payment processing compliance to protect their cardholders from security threats and fraud.

Using a set of qualifications to determine the safety of a point of sale terminal or ecommerce website, these standards are now mandatory best practices between businesses who process card payments and their customers.

The standards for PCI compliance are as follows:

  • Install and maintain a firewall configuration to protect cardholder data
  • Do not use vendor-supplied defaults for system passwords and other security parameters
  • Protect stored cardholder data
  • Encrypt transmission of cardholder data across open, public networks 
  • Use and regularly update anti-virus software or programs
  • Develop and maintain secure systems and applications
  • Restrict access to cardholder data by business need to know
  • Assign a unique ID to each person with computer access
  • Restrict physical access to cardholder data
  • Track and monitor all access to network resources and cardholder data
  • Regularly test security systems and processes
  • Maintain a policy that addresses information security for all personnel

For developers, a separate set of standards has been set by the PCI SSC to ensure websites are processing electronic payments securely:

  1. Do not retain full magnetic stripe, card verification code or value (CAV2, CID, CVC2, CVV2), or PIN block data
  2. Protect stored cardholder data 
  3. Provide secure authentication features 
  4. Log payment application activity
  5. Develop secure payment applications
  6. Protect wireless transmissions
  7. Test payment applications to address vulnerabilities
  8. Facilitate secure network implementation
  9. Cardholder data must never be stored on a server connected to the Internet
  10. Facilitate secure remote access to payment application
  11. Encrypt sensitive traffic over public networks
  12. Encrypt all non-console administrative access
  13. Maintain instructional documentation and training programs for customers, resellers, and integrators
  14. Maintain instructional documentation and training prog

Penalty fines for non compliance can range between $5,000 and $100,000 a month, and inevitably wind up being the merchant’s responsibility. Additionally, merchants can face steeper transaction processing fees, or even the inability to process electronic payments for their customers in the future for non-compliance.

What Developers Need to Know About PCI Compliance

Thankfully, payment applications and payment gateways have taken care of much of the technical side of ensuring that payments are processed securely. As a developer or site builder, your primary responsibility where PCI compliance is concerned is to ensure that your applications meet the PCI SSC’s standards and stay up to date.

PCI compliance standards are determined by the volume of transactions which a merchant processes. The merchant is assigned a compliance level requirement based on the volume of business that he or she does, and the security of their sites may be tested by an approved scanning vendor, or ASV.


Ecommerce sites fall under PCI SAQ 3.1 and have the following standards:

Whether your client requires an ASV really depends on which payment processors and ecommerce applications you’re running their site on. These charts depict the flow of data, so that you can determine whether your client’s site will need an ASV or not.

The burden of site security is ultimately on the site administrator, which may be you. If that’s the case, the strongest prevention for noncompliance is pretty straightforward:

  • Make sure plugins stay up to date
  • Ensure that software updates and security patches get installed
  • Maintain stringent server security standards
  • Make sure ecommerce applications are up to date

What End of Life Means for PCI Compliance

Recently, Magento 1 reached end-of-life, putting thousands of ecommerce sites into a compliance grey area when Adobe stopped issuing official security updates.

While the ecommerce application itself represents only a small part of what PCI compliance truly entails, for merchants still running their ecommerce sites on Magento 1, the important thing to note is there will no longer be security patches and updates issued for the platform. They’re on their own unless they’ve invested in a solution like Hostdedi Safe Harbor

This primarily applies to number seven in the list of PCI compliance measures for developers:

Test payment applications to address vulnerabilities.

With Magento no longer looking after security updates for Magento 1 users, it begs the question: can an ecommerce site be PCI compliant on an ecommerce application that’s reached end of life?

Yes. Hostdedi has done it with Safe Harbor. 

What to Do When a Platform Reaches End of Life

Magento was built on Hostdedi servers. When Magento 1 started approaching end of life, our engineering team jumped to work developing a solution that would allow merchants to decide for themselves when to migrate.

For many Magento 1 store owners, making the move to Magento 2 in the wake of COVID-19 wasn’t financially realistic. Site migrations are expensive and complex, and with so much upheaval and uncertainty, many were understandably scared to make the leap.

So the engineering team at Hostdedi came up with a compromise. Hostdedi Safe Harbor was built to address Magento 1 end-of-life, keeping ecommerce sites and stores owners PCI compliant until at LEAST the end of 2021, so they can migrate on their own time.

With regular security patches made by the team who literally started with Magento, Hostdedi is able to keep Magento 1 sites and stores PCI compliant until they’re ready to make the switch.

End of life doesn’t have to mean the end of PCI compliance.

Get more time, and keep customer data safe with Hostdedi Safe Harbor.

Click here to learn more about Hostdedi Safe Harbor, or open the chat window at the bottom right of your screen to speak to sales.

Source link

How to Duplicate a WordPress Page or Post

WordPress includes a number of features in its core but a number of features you would think would be included fall into the realm of plugins. One such feature is the ability to duplicate an existing page, post, or custom post type on a site using WordPress. 

Luckily, there are a number of solid and easy to use plugins to enable page, post, or any custom post type to be duplicated. One of those plugins is called Yoast Duplicate Post. Using this plugin makes it easy to duplicate a site’s web page or post in WordPress.

How to Install and Activate Yoast Duplicate Post

Go about installing as you would do for any plugin from wp-admin go to:

Plugins > Add New

Then go search for Yoast Duplicate Post and then install and activate the plugin.

How to use Yoast Duplicate Post

Once the Yoast Duplicate Post plugin has been installed and activated it will add a new sub-menu item in settings within wp-admin on the site.

Settings > Duplicate Post

What to Copy


Yoast Duplicate Post plugin supports page, posts, and a number of custom post types. You can also use the plugin to duplicate products and coupons in WooCommerce.

Settings > Duplicate Post > Permissions

When you have the Yoast Duplicate Post setup as you want to cover all of the post types that you might need to duplicate on a site now comes in how you would go about creating a duplicate page or post.

In the page list screen in wp-admin when you mouse over the pages on the site, select the page you want to clone. Once you have cloned the page you will see a new page that is set to be with a post status of draft with the same page title as before.

The clone will show on posts, products as well as any other post types that you might have on the site and those that have been enabled to be supported in the Yoast Duplicate Post plugin.

The Yoast Duplicate Post plugin also includes a number of filters and actions which can be found from this link. Some of the included filters include custom fields that you might not want to be copied when creating a duplicate, if you needed to alter custom fields after a duplicate was created that is also possible.

How to Install and Activate Duplicate Page

There is another plugin option to be able to duplicate a page or post and it is called Duplicate Page.

Go to Plugins > Add New

Then search for duplicate page and you find the plugin to install.

How to use Duplicate Page

The Duplicate Page plugin will add a new sub-menu item into;

Settings > Duplicate Page

You can set which editor the page or post should be created using, the duplicate post status that the new duplicate page or post will be set as, and also you can see what happens after the page or post has been duplicated for the redirect.

In either the post or page list screen, the same will apply for any custom post types that exist on the site such as products if using WooCommerce. Next to the post or page click on the Duplicate This wording and a new duplicate post or page will be created.

Why Would I Want to Duplicate a Page?

Some of the reasons why you might need to duplicate a page, post, or a product would be if you are trying to use a different plugin on a specific page and you want a copy of the page before you update and use a different shortcode on it.

If you are using WooCommerce on the site, you might have a similar product to sell, and the easiest way is to duplicate an existing product. You can use the new duplicated page to update from instead of having to input all of the data from scratch again. If you had a number of changes to make to an existing product but wanted to have a backup copy, then being able to easily clone the product will help.

Source link

The One Thing You Can Do (Without Code) To Speed Up Your Store

You probably already know this, but if your site takes three seconds to load, you’ll likely see more than 50% of your traffic disappear. That’s horrible news if you’re running a blog or business site, but it’s catastrophic if you’re running an online store.

The tips on store performance optimization are endless

Maybe you read about AirBnB, and how they increased their performance by 8% using Google Tag Manager. And that sounds great until you realize that it may be more technical than you’re comfortable with.

Or maybe you’ve read articles that give you a list of things you can do to speed up your store. Below are three articles that help store owners running on Shopify.

You won’t have to spend much time on those sites to discover that they recommend that you use GTmetrix and Google’s PageSpeed Insights tool to get tips to help you find the slow spots on your store.

The problem? 

These tools were created for developers. And if you’re a store owner that isn’t a developer, these approaches won’t help you very much.

We surveyed more than 500 WooCommerce stores

Remember that Google statistic that said pages that take longer than 3 seconds to load get left by 53% of their audience? In a review of more than 500 WooCommerce stores across the globe, we found that the average page performance for more than 450 of them was 3.4 seconds. Ninety percent of the stores were too slow to keep customers browsing – that’s a problem!

While it’s easy to assume that the problem is WooCommerce (or WordPress) that powers the store, we’ve found that there’s a more important culprit – the hosting provider.

The single biggest factor that affects the performance of your store is the hosting configuration that comes from the host you’ve chosen. 

It’s like buying a new car that looks beautiful, comes with a great leather interior, a fantastic stereo and enough space for your entire family and a few friends. If you noticed the performance wasn’t what you wanted, you wouldn’t start by emptying the trunk, would you? No way! You’d check to see if the engine was working.

If your store isn’t performing well, image compression is a great idea but it’s not where you should start. You start with the engine that powers your store – and that’s your hosting environment.

Not all WooCommerce hosting is equal

When you compare hosting companies, there’s a difference between what’s possible and what’s probable. Every host can tell you that they can help your store run well. They’re telling you what’s possible. But that doesn’t mean that you’ll enjoy that performance as a probability.

WooCommerce runs on WordPress and there are a lot of hosting companies that have created solutions focused on WordPress. Right off the bat, those hosts will run a WordPress site faster than hosting companies that don’t specialize in WordPress.

Maybe you’ve heard of one or more of these companies that have created dedicated solutions for WordPress sites. They are, by far, the most famous hosting companies that work with WordPress.

  • Bluehost
  • GoDaddy
  • WP Engine
  • SiteGround

Each of these companies have invested in infrastructure and built custom solutions that help speed up your WordPress websites.

What’s critical to understand is that the very investment that was made to ensure that WordPress sites run fast may not serve your needs when running WooCommerce.

Caching Layers may help WordPress but not WooCommerce

There’s a good chance you’ve already heard different people talk about cache as a magical solution. For the uninitiated, cache is the temporary storage of parts of your website so that customers don’t need to wait for your servers to generate the content again. It’s a shortcut.

If you’ve ever walked thru an airport at lunch time you’ve likely noticed the pizza stands that have personal pizzas pre-made and pre-heated so that you could easily walk up, grab a pizza, pay and walk away. Compare that to the time it would take to order and have a custom pizza made for you, and you’ll easily see why people talk about cache as a great way to deliver high performance to customers.

But these airport pizza places work well precisely because they don’t treat every customer as a unique customer that has unique wants and needs. And the same is true when it comes to the difference between WordPress and WooCommerce.

If you run a WordPress blog or site, the pages you’ve created can be prebuilt and stored, ready for your readers because the pages are the same every time. So having them ready makes things really fast.

But if you do that with your shopping cart, where every customer gets the same cart, with the same items in it, it’s easy to consider that a disaster. Every customer needs to browse the store separately with their own cart. You can’t cache that interaction.

And that’s why we say that the strategies and investments many hosts have made, deep investments, into caching systems don’t actually help WooCommerce stores at all.

Can we talk about another technical aspect of your store?

Imagine you were shopping at a Walmart or Costco, for just a second. Imagine you filled your physical shopping cart and headed to the checkout area. That’s when you notice that there are 20 cash registers but only 2 people checking customers out.

Pretty crazy, right? Well, most hosting companies are just like that. 

Let me explain. Most hosting companies like to talk about storage and memory (hard drive and RAM) as the factors that you need to consider when it comes to the plan you choose. But if we think about your shopping trip, the amount of storage your minivan or truck has is pretty immaterial when you’re in a line of 20 customers waiting to check out. And the credit limit on the card you’re about to use to pay for your purchase isn’t much help either.

What you need is more cashiers. In the hosting world, for stores running on WordPress and WooCommerce – both written in PHP – those are called PHP workers.

When those hosting companies built their platforms, they were counting on their caching systems to ensure that you didn’t need so many PHP workers. The cache would help. And that’s true for WordPress sites and blogs. But it’s not true for WooCommerce stores.

This is why we say not all WooCommerce hosting is the same.

What store owners can do to speed up their WooCommerce store

We promised you that there was something you could do to speed up your WooCommerce without writing any code. By now you likely know what we’re going to tell you.

The simplest thing you can do to get performance gains without doing any development work at all is to change your hosting provider.

But don’t take my word for it. Let’s look at the numbers.

Here’s what we did to compare store performance

The first thing we did was create a sample store. 

  • This store had 2000 products in it
  • We then loaded more than 37,000 orders
  • Then we added more than 9,000 customers

Once we had a sample store, we bought hosting plans at mulitple hosting companies and imported our store onto each of them.

From there we created two sample paths of user interactions – store browsing and store buying. In the first case we navigated between the main catalog and the product pages. In the second, we added items to the cart and checked out.

We did these tests with varying loads – from 50 virtual users to 200 virtual users hitting the store – for fifteen minutes.

Here are the performance results for the same WooCommerce store

HOST Browsing – 50 VU Browsing – 200 VU Buying – 50 VU
BlueHost 10.14 s – 12 min  Too Many Errors 4.59 s – 12 min
GoDaddy** 317 – 429 ms 390 ms – 6.77 s 772 ms – 2.48 s
WP Engine 3.13 – 3.21 s 3.16 – 3.21 s 5.08 – 6.03 s
SiteGround 1.89 – 4.74 s 2.52 s – 2 min, 42 s 2.93 – 58.54 s
Kinsta 1.91 – 2.46 s 1.95 – 2.17 s 1.73 – 1.91 s
Liquid Web 1.65 – 1.99 s 1.67 – 1.76 s 1.65 – 1.88 s

** GoDaddy is one of the hosts that has an aggressive cache in place that makes it great for WordPress sites but completely incompatible for WooCommerce stores. Because it’s impossible to turn off their caching, orders are not able to be processed. The result is a very fast page load that doesn’t allow customers to buy anything.

The comparison isn’t much of a comparison, is it?

There is no question that you could optimize a store to perform better on every one of the hosts we compared. If you were a developer, you could look for tips that help you minify your JavaScript, use tools to compress your images, and more. We strongly suggest getting a development partner to help your store.


The one thing that both Kinsta and Liquid Web have in common is that they’re relatively newcomers to the WordPress and WooCommerce hosting environment. We normally get hesitant about new companies, waiting to see how things pan out. But what these two hosts have demonstrated is that the older paradigm of building cache-heavy solutions for WordPress hosting isn’t a solution for today’s highly interactive sites and stores.

In the case of Liquid Web that provides a dedicated solution for WooCommerce hosting, they go further by automatically optimizing images, adding performance tuning, and database-specific optimizations for WooCommerce stores.

The point we’re making here is that store owners have one move that could change the performance of their stores without any coding. And the result of that change could be a 30-300% different in load times. 

Most importantly, a faster store delivers a better experience for customers, and that’s a difference that leads to greater revenue.

Source link

5 Real Differences Between Cheap Hosting and Good Hosting

Have you ever looked at the price difference between two products and gone, “What the hell?? WHY is that one so much cheaper?”

It’s like buying something on Wish versus at Target – price is everything, but a race to the bottom is not without consequences. You get what you pay for typically, and when it comes to hosting technology, that’s especially true.

With so much technical terminology, it’s hard to really communicate exactly what the difference is between two dollar and 20 dollar hosting. It all sounds pretty much the same, right?

Fast. Secure. Reliable.

We’re normally pretty nice guys around here, but we’re also crazy honest – there’s a reason we don’t feel bad for not being the cheapest, and it’s the same reason that Target doesn’t feel bad for not being more like Wish.

What’s the Difference Between Managed and Unmanaged Hosting?

  • Application updates
  • Plugin updates
  • Malware monitoring

With managed applications from Hostdedi, you’re also getting a support team made of application subject matter experts, who understand coding and these applications enough to help you diagnose problems on both sides of things.

How Much Does Hosting Usually Cost?

Buying hosting is kinda like buying a data plan. You get a connection to a server, you get data limitations and storage space, and some technical infrastructure on the back end to make sure that everything is running smoothly.

On the managed hosting side of things, like what we do here at Hostdedi, you get a lot more than just that connection and storage space. You get a level of administrative service that, though largely automated, keeps your plugins working together nicely and your site up to date (because let’s face it: we all forget).

Hosting plans are structured similarly to data plans in that you get a certain amount of bandwidth and features and functionality at staggered price points.

For a simple website, hosting typically costs between $3 and $45 per month for basic, unmanaged hosting. For managed hosting, the range is more like $7 to $45 per month.

As you’re getting into more complex projects, like ecommerce websites, or sites with a lot of traffic and complex server demands, those plans tend to get more expensive. 

The 5 Skeletons Hiding In Cheap Hosting’s Closet

#1 – Unlimited Bandwidth Isn’t Actually Unlimited

Have you ever increased your data plan for your home internet, only to find that your data overages turned into a slower connection?

It’s not in your head. This is called throttling, and it’s what happens when a user eats up a lot of bandwidth, but can’t be charged any overage fees.

The same thing is true for hosting. Though many cheap hosts claim to offer unlimited bandwidth, the reality is that there’s no such thing. Unless you’re dealing with a host with cloud infrastructure, it’s literally impossible for the bandwidth to be unlimited because you’re dealing with a physical server with physical capacity limitations.

#2 – They Use the Fine Print to Throttle Your Speed

Since unlimited bandwidth isn’t actually a thing, a lot of cheap hosting providers put weird clauses in their terms of service to make it technically legal for them to call their service unlimited, and then still, well, limit it.

For example, Godaddy has an ecommerce plan that offers unlimited bandwidth. The only catch? It’s against their terms of service to upload multimedia content to your website. No product videos for you, buddy.

#3 – Traffic Surges Will Produce 502 Errors

Related to unlimited bandwidth is a physical server’s inability to automatically scale your bandwidth and concurrency needs when you get a surge of traffic.

Long story short, if you have cheap hosting and you plan on killing it this holiday shopping season, you’re more likely to see llost sales due to 502 errors than record-breaking numbers.

#4 – When It Comes to Applications, You’re On Your Own

Cheap hosts typically have a very narrow scope of support. What this means is that when you’re having an issue and using an application, like WordPress or WooCommerce, you’re not likely to get much help out of them.

If it’s not server-side, you’re out of luck. They’re going to send you to the application’s support team, who will in turn, likely send you back and forth with a series of things to try, until you eventually scream in agony and throw your laptop out the nearest window.

Not good.

#5 – Cheap Hosting Usually Comes With a Long Term Commitment

In a lot of cases, cheap hosts know what they’re selling, and they know better than to make it easy for you to just walk away. That’s why in a lot of cases, those $3 hosting providers are going to try to get you to commit to a long term agreement that you’ll have to pay to get out of early.

Look, hosting is like the foundation and walls of your house. If someone asked you where you’d like to save money in building your new home, would you start there?

Of course not. Because literally your entire home is built on that stuff.

Hosting is no different, and scrimping on it to save a few bucks a month is akin to hiring the sketchiest contractor you can find to pour your foundation. It’s not worth the risk, and you don’t have to spend a lot to get great hosting anyway.

Buck up ya cheapskate – you’re not building websites because you have a ton of free time. You’re building them because you want your work out there in the world and you have a vision.

Don’t build your vision on a flimsy hosting foundation – build it with Hostdedi.

Free Trials

Source link

Adding Custom Triggers to AutomateWoo

Email marketing is key to running an effective eCommerce site. While there are many good email marketing platforms out there, many don’t have very deep interactions with WooCommerce. If you start looking at all the plugins available for WooCommerce and their capabilities, there are almost no email marketing platforms that interact with many of the different events you’ll want to use.

This is where AutomateWoo fills a huge gap. AutomateWoo is built specifically for WooCommerce; to automate your customer interactions completely inside your WordPress admin interface. This means that it has fairly deep hooks into WooCommerce that you can leverage. This also means that it’s built using WordPress best practices for plugin development and doesn’t need to interact with a 3rd party server.

Today we’re going to take a look at what AutomateWoo can do for you out of the box. Then I’m going to walk you through the process of creating a custom trigger for those few times that AutomateWoo doesn’t cover one of your use cases.

AutomateWoo Trigger Basics

AutomateWoo works by detecting actions that users take. Once an action is recognized by the plugin, it allows you to trigger events. If that sounds a bit confusing, let’s use AutomateWoo to send a thank you email to a customer once they have spent over $200 in our store.

To start go to AutomateWoo -> Workflows and then click Add Workflow at the top of the page.

Next, create a descriptive title for your Workflow. I titled mine Customer Spend Reaches

Now we need to choose the trigger we want to use. Click on the select box and choose Customer Total Spend Reaches from the list of available triggers and then set the total spend value to $200.

Now we need to choose an action to take when a customer spends more than $200 in our store. Click the blue + Add Action button and choose Send Email as the action we want to take.

As you fill in what you want to say to a customer remember that you can use any of the variables that are listed on the right-hand side of the screen. To use a variable you need to use double curly braces around the variable name. That means to use the customer’s first name (if they have one in your system) you’ll use {{customer.first_name}} in your text where you want that information to show up.

Once you’ve got the email content you want, scroll back to the top of the page and click the blue Save button so that your Workflow is saved and ready to go. If you’re working on a Workflow, you can change the status of it to Disabled and then click Save. Marking a Workflow as Disabled will ensure it doesn’t run while you’re working on it.

Do pay attention to the status of a Workflow. I’ve had workflows running that I didn’t want running, and also thought I had a workflow active that was disabled. Always double-check the status of your workflow once you’ve finished working with it for the day.

One feature of AutomateWoo we haven’t touched on yet is their rules. Rules allow you to filter which type of customer a rule works for. You could use two different rules to reward the repeat customer above based on where they are. Maybe you can mail customers in your country a card and you use a rule to send yourself an email with their address when they reach the threshold. For users outside your country, you could send the email above instead of the card.

Create a Custom AutomateWoo Trigger for WooCommerce Teams

Despite the deep hooks that AutomateWoo has in WooCommerce, it doesn’t cover every case for every plugin. For a client I worked with recently, we wanted to send each new team member an email as they were added to a team inside Teams for WooCommerce Memberships. AutomateWoo doesn’t provide a trigger for this out of the box, but it is possible to add your own custom triggers to AutomateWoo.

To start we need a base plugin, which you can see below.

<script src=””></script>

While it’s possible to have a single plugin file and include all the custom triggers you may want, I don’t like doing that unless I’m 100% sure that I’m only adding a single trigger. If you end up adding more than one or two triggers you end up with a huge plugin file with functions spread all over and it becomes hard to manage which trigger your dealing with at any one time. Instead, I like to keep each trigger in its own file and include them in the main plugin. This makes it easy to pick out which trigger you’re working on.

We will need to include the main trigger registration in the plugin though, so let’s do that and include the file that will contain our trigger. Inside our init function add the trigger filter.

add_filter( 'automatewoo/triggers', array( $this, 'add_to_team_trigger' ), 10, 1 );

That’s a filter hook in WordPress. Filters allow you to change data as it passes through the code. In this case, we’re going to add to an array in the next block of code.

This in turn calls a function called add_to_team_trigger which will register our new trigger for AutomateWoo. Just below our init function add the following code, which should make your base plugin look like this.

public static function add_to_team_trigger( $triggers ){

    require_once( 'trigger-add-to-team.php' );

    $triggers['nexcess_add_to_team'] = 'Nexcess_Add_To_Team_Trigger';

    return $triggers;


Note that just before we adding to the $triggers array, we required a file called trigger-add-to-team.php. Now we need to create that file so that we have a trigger in AutomateWoo. Create a file called trigger-add-to-team.php in your plugin folder and then paste the code below into it.

<script src=""></script>

Now, let’s walk through what the code is doing. Lines 3 – 5 are about security. They stop anyone up to no good from directly accessing the file itself. Next, we define a class called Nexcess_Add_To_Team_Trigger which extends the base functionality of AutomateWoo’s Trigger class. Line 14 defines the data that is passed to our trigger.

In our init function we define two things. First, we define the name of our hook and second, we say what group it should go in. You can use the existing groups in AutomateWoo or you can define a custom group. In this case, we used the Team group because the trigger is related to WooCommerce Teams. Any future team trigger would go in the same group.

If our trigger needed to load any custom UI elements we’d use the load_fields function. We don’t have any (and I’ve never needed any) so we’ll just leave that alone.

The register_hooks function is what catches what’s happening in WooCommerce teams so that we can do something when a new team member is added. If we go to the Team.php file in WooCommerce Memberships for Teams and go to the end of our add_member function we’ll see that once a team member has been added successfully it calls the hook named wc_memberships_for_teams_add_team_member.

Note that wc_memberships_for_teams_add_team_member passes the Member object and not a user_id which is what AutomateWoo expects to get on line 47. That means we need to take the Member object and get the user_id from it on lines 43 and 44 so that we can pass the user_id to AutomateWoo.

wc_memberships_for_teams_add_team_member is an action hook. This allows you to detect when an event happens in WordPress so that you can do something else based on the occurrence of the event. You can read more about WordPress Hooks in the documentation.

By adding to this action hook we run our trigger once a new member has been added to a team.

Next our catch_hooks function is called by the register_hooks function, specifically it’s called here when the wc_memberships_for_teams_add_team_member action is run. This is going to pass the user_id to the rest of AutomateWoo so that we can send a user an email.

The result of all this code is that if we create a new Workflow in AutomateWoo we see that we have a new trigger which lets us run a Workflow when a new user is added to a team. Make sure your custom plugin is activated and then create a new workflow using our new trigger.

That’s it, we now have our custom trigger working for AutomateWoo. You can see the completed plugin here

To add custom triggers for other events on your site you’ll need to look for other action hooks so you can detect different events as they happen. Using pretty much the same code above I could also email a user when they are removed from a team by using the wc_memberships_for_teams_after_remove_team_member hook in the same Teams.php file.

Source link

Magecart Attacks Again: the Latest on CardBleed

Only a couple of weeks after the first vulnerability with an associated CVE was discovered for Magento 1 after its end of life, reports about a large scale Magento 1 hack attempt surfaced. 

While stats are not definitive, as of today, around 3,000 sites were hacked. This attack, usually referred to as MageCart, is the most common type of attack against Magento 1 and it’s typically used to collect user credentials and credit card information from the application inputs and exfiltrate data to remote servers.

After carefully reviewing public reports and our WAF logs, Hostdedi identified the threat and swiftly added a fleet-wide block for /downloader. We also isolated the malicious content added to this prototype.js file and have removed it from every file, leaving the original malicious file as backup (prototype.js.bk) for the client’s reference. 

We already had filters for this, mostly against brute force attacks. But given that Magento discontinued Magento Connect after June 2020, we decided to block access and only re-enable it upon request for certain IPs. 

This is one of the biggest differences between a code based Magento 1 maintenance package versus a hosting-based approach. While almost every project issued notices and recommendations, they all required user intervention. 

Our approach was to deploy a fix to the entire server fleet without any user intervention.

While a few stores were impacted, the immense majority remained safe because of the infrastructure and systems we already had put in place. This foundation, plus our swift action, helped thousands of Hostdedi stores and customers to remain secure.

In addition, we released Nexcess_CSP for our Safe Harbor users. Content Security Policy (CSP) is an added layer of security that helps detect and mitigate certain types of attacks including Cross Site Scripting (XSS) and data injection attacks usually known as MageCart. This module helps any Magento 1 store to set CSP policies, avoid and report XSS attacks and has 2 main objectives:

  • Mitigate cross site scripting: disallowing the communication to certain URLs by specifying the domains that the browser should consider to be safe sources of scripts.
  • Mitigating package sniffing attacks: specifying which protocols are allowed to be used; a server can specify that all content must be loaded using HTTPS.

We did not find any intrusion for stores that had CSP_Nexcess installed and properly configured.  Hostdedi Safe Harbor provides an extra layer of protection against this type of attacks, which are likely to continue.

The best kind of protection against external attacks is a mix of server side protection in the form of a WAF plus modules and patches to keep your store protected.

Keeping your Magento 1 store fully operational means protecting it against known vulnerabilities. If you have yet to invest in Safe Harbor, this hack illustrates the importance of staying secure.

Hostdedi Safe Harbor is a sound foundation to keep your sites and stores protected while you are on M1.

Source link

Passing the Torch – Hostdedi Blog

No matter where you stand politically, you can’t deny that Ruth Bader Ginsberg was a force. I have a special place in my heart for her as we’re both from Brooklyn. Her demeanor, her mannerisms, and her grit take me back to the 1970’s-1980’s New York of my youth. You don’t mess with Native Brooklynites. We don’t all sound like Tony Manero, but our strut is innate.

As working men and women, there are many reasons to be grateful for RBG’s contributions to our society. Her history is now documented everywhere – from no one hiring her after she graduated first in her class from Columbia, to losing her job because she got pregnant. Her personal challenges and beliefs drove her to fight for justice and equal protection under the law for all of us. 

Navigating a Path to Leadership

I have worked in tech for 20+ years and we all know the stories. With the exception of crossing paths with one or two extraordinary female leaders during my career, I’ve seen first-hand the limitations and struggles faced by women, including myself, to navigate a path to leadership. When I landed at Hostdedi, the tides turned. It’s not lost on me that my peers and I are incredibly fortunate to work for a company that hires really smart individuals to do really smart things. Our culture, built on entrepreneurship, supports our strengths, our skill sets, and the ability to learn as you go. 

Our COO is one of those extraordinary women. And we’ve got a plethora of women in leadership roles across the organization – Marketing, Operations, Sales, and Channel. We are surrounded by team members who recognize our achievements, respect our work, and look to us to pave the way as they navigate their own careers. 

We didn’t get here by playing it safe. We all took risks. Got shot down. Were likely bypassed for promotions. Had others steal our ideas and claim them for their own. Maybe we didn’t talk enough. Or maybe we talked too much. Many of us had to figure out how to juggle managing a household and being a parent while still striving for professional success. These challenges are faced across traditional fields for women working outside of the home, but tech offers its own set of obstacles to overcome. Tenacity and confidence are key drivers that ensure you never give up on yourself. Even if others do. 

A North Star for All of Us

RBG’s persistence and attitude towards her professional mission should be a North Star for all of us. A strong sense of self, confidence that doesn’t turn into arrogance, an honest interest in helping others, a passion for learning, and an ability to grow and evolve.These are key attributes for every leader, no matter their gender. 

It is our duty to offer career paths to those that follow us. Opportunities to learn and grow. Mentorship to address issues that may be better than they were yesterday, but still require navigation. To empower our teams, welcome their ideas, be confident enough to recognize better ideas, and allow everyone to pursue greatness. 

Thank you, Ruth. We will take what you’ve given us and pass the torch. 

Source link

Deploy WordPress with Github Actions

A while back I showed you how to deploy your WordPress site with Deploybot. I’ve used this service for years now, but when I started, it was out of my price range, so I used nothing and made many mistakes deploying my sites which cost me many lost hours and some tears.

Today, I’m going to walk you through how to use Github Actions to deploy your site automatically for no cost. The set up is more complex than Deploybot, but it’s going to be free for most projects.

This post has a bunch of working parts so set aside some time, especially if you haven’t worked with Git or SSH keys before. We’re going to cover:

  • Creating a Hosting Account
  • Getting your code into Git
  • Creating special deploy SSH keys for Github to use
  • Configuring the Github Actions YAML file
  • Using Github repository secrets to keep private information safe
  • rsync via ssh

What Are Github Actions?

Github Actions is a feature of Github that allows you to automatically perform tasks based on the state of your code. Today, we’ll look at deployment, but you could also have an action to run your unit tests or notify a Slack chat when someone makes a new PR on your project.

While they may take a bit of time and effort to set up your first time, they return the investment by letting you get back to code instead of worrying about repeating the same work over and over. 

Getting Your Site Set up

The first thing you’ll need is to create a hosting account on Hostdedi, so head over and check out the plans available. The Maker WordPress plan is a good plan if you’re hosting a few sites.

With your site set up, go to the backups and create a backup of the site before you do anything else. Make sure you download this backup as well so you have a copy on your computer…just in case.

Unzip the backup and then copy out the public_html folder to use as our git repository. You can remove the wp-config.php file because we won’t need it today.

Now that we have our copy of the repository downloaded, let’s add it to Github. To start we’ll need to create a new repository in Github. Add your title and whatever description you want, I usually don’t initialize the repository with a README because I’ll provide my own with any project-specific notes and documentation for a client project.

Next, open up Terminal and cd into the downloaded copy of WordPress so you can initialize the repository with git init. The first thing we want to do is add our .gitignore file so that we don’t add any files that may overwrite what Hostdedi needs to run your site. You can use the .gitignore file provided below.

The top eight lines are specific to Hostdedi, so make sure you copy those lines if you have your own preferred ignore configuration.

If you’re not familiar with Git, check out my post on Introduction to Git.












































Now that you have the ignore file ready, use git add and git commit to add the WordPress files to your repository. Then push those files to your Github repository.

Creating a Deploy SSH Key for Github

To deploy our site via Github Actions, we’ll need an SSH key for the action to use. Do not use your regular SSH key.

To generate the SSH keys needed use the command below using your email. When prompted for a passphrase, press enter and leave it blank. When you’re asked for a location, choose a location to store them temporarily. You can find Github’s documentation on SSH keys with extra details here.

ssh-keygen -t rsa -b 4096 -C "[email protected]"

Before we take the next step, make sure your new SSH keys are stored safely. I store them in my 1Password vault alongside the other server credentials. Don’t leave them sitting in some folder on your computer because if someone gets your keys they get access to any server those keys are used on.

Now, open the public key (the one that ends in .pub) and open it in the text editor of your choice. In your Hostdedi account, click on your account name in the top right corner and select SSH Keys.

Next, select Add Key and copy/paste the whole key out into the main text field. Make sure to label your key properly so you can tell what the key is being used for.

Finally, click Add to save the key to your account.

Adding and Configuring Your Github Action

Before we start to build our action, we’ll need some secret information stored in our account. Stuff like our private key for the key pair we just created, the location of our server, and the entry for the known_hosts file.

Start this by choosing Settings from the top right of your repository. Then choose Secrets from the left column. We’re going to add 3 different values.

  1. DEPLOY_SSH_KEY: This is the private key we generated (doesn’t have .pub at the end)
  2. NEXCESS_LOCATION: The location SSH will access on our server plus the file path to your html directory. Making a mistake here could delete your site, but this is why we took a backup.
  3. NEXCESS_HOST: The allowed host file we need from our server

You already have 1 so open your key file and copy it’s entire contents into a secret called DEPLOY_SSH_KEY.

Next, you can get the location of your server from your Hostdedi control panel for your site under the Access menu.

Finally, the easiest way to get the content for NEXCESS_HOST is to ssh into your server from your computer. This should prompt you to accept a new known server. Accept the new server and then you can head to ~/.ssh/known_hosts and get the last line in the file for the secret you need to add to your repository.

Why are we keeping this stuff secret? Each of these pieces of information has some security risk so you don’t want them in your repository. Putting them in a secret variable in Github makes sure you don’t expose information by accident.

We’re ready to head back over to our repository on Github and get our action going. Start by going to the Actions menu at the top of your repository and click on it. While there are lots of prebuilt actions, we’re going to start by creating our own action so select that from the Actions screen.

Doing this will give you a basic workflow file written in YAML. By default, it works only on your master branch, but by changing which branch is in the arguments on lines 9 & 11 you can make it work for a different branch. You may do this if you wanted to deploy from a staging branch to a staging site and from master to the live site.

Starting with the line below, delete the rest of your default workflow file.

# Runs a single command using the runners shell

    - name: Run a one-line script

      run: echo Hello, world

Now we need to get our SSH agent. On the right hand side of the workflow screen search for webfactory/ssh-agent.

Click on this and it will provide you with some commands to copy and paste into the bottom of your file, but we’re going to use our own custom script. Copy the code below and paste it into your workflow file below the actions/checkout@v2line.

   # Setting up SSH

    - name: Setup SSH agent

      uses: webfactory/[email protected]


        ssh-private-key: ${{ secrets.DEPLOY_SSH_KEY }}

    - name: Setup known_hosts

      run: echo '${{ secrets.NEXCESS_HOST }}' >> ~/.ssh/known_hosts

    - name: Sync project files

      run: rsync -uvzr --backup --backup-dir='~/deploy-backup/' --exclude 'wp-config.php' --exclude '.gitignore' --exclude '.git/*' --exclude 'wp-content/uploads/*' --exclude '.htaccess' --exclude 'wp-content/cache/*' --exclude 'wp-content/advanced-cache.php' --exclude 'wp-content/object-cache.php' --exclude 'wp-content/mu-plugins/*' ${GITHUB_WORKSPACE}/ ${{ secrets.NEXCESS_LOCATION }}

You can see the secrets we set up earlier in this file. It starts by pulling in the ssh-agent and adds our private DEPLOY_SSH_KEY to the server it’s getting ready in the background. Next, it adds our server as a known host.

It finishes by syncing the project files over to the live server in a long rsync command. In short, it backs up the remote server into a directory called deploy-backup and then moves any new files in the Github project over to the live server. We excluded all the same location we ignored in our original .gitignore file so that rsync doesn’t touch them by accident.

If you want to read up on each rsync command there, I usually refer to this Ubuntu documentation on rsync

Now all you need to do is make some changes in your repository and then use git to add and commit them to your repository. Push those changes to Github, and the action will automatically backup your files and then push your changes over to your site.

If you’re new to automatic deployments, this does seem like a lot of work. Even my first time using Github Actions to deploy my site I spent a few days working on the script. This doesn’t feel like it saves time until I’m using the same script for weeks with a project deploying regularly.

Automating your deployment, and taking the time to get it right, means you never accidentally overwrite the wrong files, put the wrong files in the wrong directory, or make any other of the many mistakes I’ve made moving files around in the 12 years I’ve been building sites.

A day or two of time spent configuring deployment for your first time is worth saving that pain.

Source link