Hide Admin Messages from Subscribers

Do you want all your WordPress logged in users to see your system messages?

Messages declaring pending plugin updates, a WordPress core update, or a notification from a plugin, all visible to any logged in user.

Lets keep the info given to registered users of your website to a minimum. We don’t wish to tell them about the status of the website.

There are a couple of areas to target:

  • Admin notifications
  • The notification bar

WordPress provides hooks to actions covering both of these areas.

By checking the capabilities of the user we can determine whether we wish to show the info.

The restriction uses actions and filters added to the file functions.php in the theme.

Admin Notifications

Perhaps the most important.

Checking to see whether the user is able to update the core first, this function determines whether to show admin notifications.

function show_update_notice_admin_only()
    if (!current_user_can('update_core')) {
        remove_action( 'admin_notices', 'update_nag', 3 );
add_action( 'admin_head', 'show_update_notice_admin_only', 1 );

Notification Bar

At the top of the page there is the notification bar. Lots of content on this bar we don’t want non-admin users viewing.

So can we hide it ? – Yes, using filters.

This time we are testing to see if the user is unable to perform a couple of actions.

The first test is the management of options.  If the user is unable to do so then hide the admin notification bar.

Similarly the second test checks whether the user can update posts. If this isn’t possible then again the admin notification bar is hidden.

// show admin bar only for admins
if (!current_user_can('manage_options')) {
	add_filter('show_admin_bar', '__return_false');
// show admin bar only for admins and editors
if (!current_user_can('edit_posts')) {
	add_filter('show_admin_bar', '__return_false');


WooCommerce Cross-Sell and Upsell Products

Upsell and Cross-sell products are used in WooCommerce to increase product sales.

When do these two lists of products get shown?

Let’s begin by adding some products of each type to a product.

On the Product data section there are a number of tabs running vertically at the left with the associated configuration options in the remainder of the page.

WooCommerce Cross Sell and Upsell products: linked products

Click on the tab linked products to show the upsell and cross sell options.

Linked products are added by typing a few letters from the product name and making a selection from the resulting list.

WooCommerce Cross Sell and Upsell products: adding upsell product

In the screenshot above the upsell product of Chantenay Carrots is being added.


Upsell products are shown when viewing a single product’s detail, its description, images, price and attributes

WooCommerce Cross Sell and Upsell products: view product

In this view we are seeing an individual product with below two sets of products, the upsell products and the related products, based on what we have seen before.

The upsell products are premium versions of the product selected to view. In this instance I’m showing the higher priced purple spouting and kalettes.


The list of cross sell products appears when viewing your basket of items.

Having made our product purchases. Click to view the basket.

WooCommerce Cross Sell and Upsell products: view basket

In this view we are seeing the configured cross sell products of carrots and potatoes.

With a cross-sell product we wish to encourage the shop visit to buy something relevant to the items in the basket. I’ve chosen to show more vegetables but a steamer/saucepan to cook the vegetables would also be appropriate.

How to Refresh your Browser Cache

Sometimes  the browser needs to be refreshed.

When a web site’s files, images, CSS and JavaScript, have been changed its possible for the browser not to realise the change and to continue using its older cached version.

Many times I have made a change to a client’s website, advised them that the updates are completed only for them not to see the change.

Refreshing the page view will often not update the view.

To view the changes made to the associated website files can require a forced browser cache update.

What is the Browser Cache?

Browser website cache is the local storage of website components: images, scripts and CSS rendering files.

The aim is to store a local copy of the website components such that the next time the page is visited only one or two items may need to be downloaded.

This improves the load speed of the website.

Browsers and how to reset flush their cache:

CachingRefresh browser cache typical website timeline

The image above shows the details regards the timing for the downloading of the various components of a website.

a web a page allows a browser to

By caching elements of a website the browser saves on time regards to the download of those elements.

However, if one of these elements has been updated it may mean that the change isn’t showing.

If the browser is still using its older cached version then the page will look the same as before.

So, how to force the browser to reload it’s cached items, just as if it was the first time visiting the web page?

Whilst updating customer’s websites I sometimes find that the changes are not visible in their browser when reviewing the update.

For example if an image hasn’t changed, or as shown in the image above one of the website rendering CSS files is still the same then this file doesn’t need to be downloaded.

This means that the browser can render the page much quicker – it hasn’t had to wait for the file to be downloaded.

Its also lighter on your Internet plan.

Browser shows an old version – but my file has changed

Simply refreshing your browser view of a page may not be sufficient.

Browsers tend to like to work from their cached copy of website static files. Files such as images, script files and styling are generally considered to be static.

Refreshing the browser page will allow the server to regenerate the content, perhaps with any differences. But the underlying files will be kept.

So, how do I force the browser to refresh its cache? Reloading all of the websites files as if I was visiting the site for the first time.

Force Browser Refresh

The browser will try to limit the files which it downloads. However, his can mean that files which have been updated are not realised. Rendering n older version of the file.

This effect is most visible when an image or the CSS layout file have been updated.

This is most notable during the development phase of a website.

Listed below are a number of browsers with how to force the browser to refresh its cache. Sometimes clicking on the browser refresh or pressing the often used f5 key are just not enough

Refresh browser cache Firefox refresh

We need to tell the browser to forget anything that has previously been downloaded from the website should be forgotten and download afresh.

Researching this I found that comparable methods don’t exist across all of the browsers.


I have found with Firefox that if I follow the often stated recommendation to host down the shift key and to press the f5 key I usually open a new tab.

I have found that it is preferable to hold down the shift key and to then click on the refresh icon to the right of the address bar.

Whilst testing website I have found that server errors can be particularly irritating. Firefox will fail to get the note working content from the server, rather contributing to show the server error. This does eventually time out and function correctly indeed more.


For Safari versions 9 onwards pressing the command key and R will refresh the cache.

There is also the option to click on the reload icon (at the end of the navigation bar) whilst holding down the shift key.

Google chrome

Either CRTL + F5 or <SHIFT> + F5 will work.

This may also be done from the Settings. Having selected the settings, scroll down to the bottom of the list, expanding the section Advanced. Within Privacy and security click on the option Clear browsing data. The option we’re interested in is Cached images and files. Ensure this one is ticked, untick the remainder. click on the button CLEAR BROWSING DATA.

Internet Explorer

<CTRL> + refresh ought to suffice. But its not guaranteed. With IE the better option is to clear the cache either via the tools menu or F12 key.

You may find you need to use the tools options to properly clear the cache.

Click on the gear icon and in the popup window Internet Options within the sections Browsing History click on the Delete button. This opens a new window. Untick all items except Temporary Internet files and website files. Click on Delete.


IceWeasel is effectively Firefox. It therefore acts the same.


Opera doesn’t have the equivalent of clearing the cache for the current web page. Opera settings then select delete private data. Cache empty is for all.

Click on the menu in the top left corner. And click on Settings.

The Privacy & Settings page includes the option to Clear browsing data near the top, within the Privacy section.

Clicking on the link opens a pop-up window allowing selection of the items to clear. There’s an option to select how far back in time the selection shall affect.

Whilst not giving the option to select the current page this does give a good approximation.


From the Settings menu, select Configure Konqueror.

On the pop-up window Cache is shown in the left menu as a child item of Web Browsing. Click on this.

For me I was shown the message: This configuration section is already opened in Choqok.

I closed Choqok and tried once more.

There’s a single option, a button Clear Cache.


This is one of the <SHIFT> key plus toolbar refresh icon ones.


Click on the Vivaldi icon in the top left corner and select Tools and then Clear Private Data.

On the pop-up window select cache only and set the time to Past Hour. Click on Clear Browsing Data at the bottom of the window.


How to clear the Firefox cache

Opera Help: Cache



Empty the DNN Site Log

An excessively large SiteLog table is likely to have an impact on the performance of your website. Do you know how many entries there are and whether the older ones are being cleaned out?

I have found that the DNN Site log table can be prone to growing, unrestricted.

This can be brought about by the failure to set a day limit and not enabling the scheduled clean up task.

In the past I have found values in the site log which precede the given cut-off date. Often as a result of the number of days being reduced, but the SiteLog purge not running properly.

Maybe looking through the scheduled task notifications you are seeing messages which show the purge of the site log is failing.

Failure of the scheduled task to run is often a sign of a table which has grown too large and is timing out on the deletion.

Information about the site log table SiteLog can be gained via the admin SQL Console.

Empty the DNN site log: count number of rows

SQL is entered within the main text area and run by clicking on Run Script.

Take care! It is easy for an entered command to wipe table contents, beyond the intended results.

The size of the table, ie. the numbers of rows in the table, can be determined by running the command:

SELECT count(*) FROM SiteLog

It’s also possible to see if there are entries earlier than your set limits.

This can be done by running the command


Shown below a typical set of results, based upon a newly enabled sitelog, with the number of columns abbreviated for clarity.

DateTime Referrer Url UserAgent
21/03/2018 12:32:00 http://localhost/Admin/Site-Settings http://localhost/Default.aspx?TabId=67&language=en-GB Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:59.0) Gecko/20100101 Firefox/59.0
21/03/2018 12:32:00 http://localhost/ http://localhost/Default.aspx?TabId=56&language=en-GB Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.186 Safari/537.36
21/03/2018 12:33:00 http://localhost/Admin/Site-Settings http://localhost/Default.aspx?TabId=67&language=en-GB Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:59.0) Gecko/20100101 Firefox/59.0
21/03/2018 12:33:00 http://localhost/Admin/Log-Viewer http://localhost/Default.aspx?TabId=21&portalid=0&language=en-GB Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:59.0) Gecko/20100101 Firefox/59.0
21/03/2018 12:33:00 http://localhost/ http://localhost/Default.aspx?TabId=56&language=en-GB Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.186 Safari/537.36

If there are entries preceding the cut-off date these may be deleted using

DELETE FROM SiteLog WHERE DateTime < given date

Dates are awkward to deal with. By default entries are stored in American date format. It is also anticipated that dates used will also be in this format too. Rather than adding formatting information when running these commands you may wish to simply accept the default format.

To ensure that you are going to delete the correct items try a selection first, based upon your date range

SELECT * FROM SiteLog WHERE DateTime < CONVERT(DATETIME, ’03/21/2018′)

From my example above I am expecting this to return no results, which is the case.

Whilst setting the date as 22/03/2018 gives:

DateTime Referrer Url UserAgent
21/03/2018 12:32:00 http://localhost/Admin/Site-Settings http://localhost/Default.aspx?TabId=67&language=en-GB Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:59.0) Gecko/20100101 Firefox/59.0
21/03/2018 12:32:00 http://localhost/ http://localhost/Default.aspx?TabId=56&language=en-GB Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.186 Safari/537.36
21/03/2018 12:33:00 http://localhost/Admin/Site-Settings http://localhost/Default.aspx?TabId=67&language=en-GB Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:59.0) Gecko/20100101 Firefox/59.0
21/03/2018 12:33:00 http://localhost/Admin/Log-Viewer http://localhost/Default.aspx?TabId=21&portalid=0&language=en-GB Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:59.0) Gecko/20100101 Firefox/59.0
21/03/2018 12:33:00 http://localhost/ http://localhost/Default.aspx?TabId=56&language=en-GB Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.186 Safari/537.36

You may also wish to sort by the datetime field descending, just to get the newer entries

SELECT TOP 20 * FROM SiteLog WHERE DateTime < CONVERT(DATETIME, ’03/21/2018′) ORDER BY DateTime DESC

It’s possible with too many entries in the SiteLog that the deletion of a range of rows will timeout.

You may wish to purge the SiteLog table. I have found that doing this via the DNN SQL control console can lead to time outs and failure to action.

If the truncation of the table times out or fails then you may find that it’s Better to perform the action via the SQL Server Management Studio, if this is available to you .

I navigate to the required database table view and click on the New Query button.

Enter the following


Refresh your table view to see the change in the number of records.

DotNetNuke can require a restart of the application to reflect changes made to the database.

With DNN 9 the site log has been removed. Although it can be added back in if you wish.

Reviewing an older site I observed that the site log still existed.

Without the original admin configuration, it’s not possible to empty the log table by following the older practices to restrict the number of days or to turn off the site log.

I chose to use the SQL truncation detailed above to empty the site log table.


A Site Log module: https://github.com/DNNCommunity/Dnn.SiteLog

Using Microformats to Indicate Address

If you run one of the online website analysis websites on your website it may indicate the use of microformats.

So what are they?

Microformats can be used to indicate the address. For example, of the contact us page of a website the address details can be enclosed.

Rather than simply putting the address in place, perhaps wrapped in paragraph tags, something like.

My Company Ltd.<br />
Apple Tree Road<br />
Reading<br />
Berkshire<br />
England<br />
RG1 1AA<br />
Tel. 0118 496 0000

The idea is to indicate to search engines the nature of the elements highlighting how the address is composed, region, city, etc.

This is all about adding clarity to the search engines and ensuring that your intent is understood clearly and correctly.

With microformats the ambiguity with regards to addresses and whether a word is a part of the address an be resolved.

For example my local town of Reading. So difficult when searching for related topics as the word doubles as in “reading a book”. There’s also a village in Somerset called Street. Putting the town name, for example Reading, on the page wrapped with microformats ensures clarity.

Here’s a typical address, with company name, address, postcode, country and telephone details.

My Company Ltd.
Apple Tree Road
Tel: 0118 496 0000
Fax: 0118 496 0001
Email: info@example.com
Open: 9am to 5pm

And here’s the micro formatting of the address.

<div itemscope itemtype="http://schema.org/Organization">
  <span itemprop="name">My company Ltd.</span>
  Contact Details:
  <div itemprop="address" itemscope itemtype="http://schema.org/PostalAddress">
    Main address:
    <span itemprop="streetAddress">Apple Tree Road</span>
    <span itemprop="postalCode">RG1 1AA</span>
    <span itemprop="addressLocality">Reading</span>,
  Tel:<span itemprop="telephone">0118 496 0000</span>,
  Fax:<span itemprop="faxNumber">0118 496 0001</span>,
  Email: <span itemprop="email">info@example.com</span>

The Schema website provides the following list of PostalAddress properties:

Property Description
addressCountry This may be either the country name of the two letter code
addressLocality The local region – often a district of a city
addressRegion The wider region – county administration, for example
postOfficeBoxNumber A PO Box number
Postalcode The Associated postcode
streetAddress The street address may be a simple building number and road, but can include building name and more than one row

Also to be considered are the ContactPoint properties which cover the telephone and email address

Property Description
areaServed Useful if you have offices providing different geographic coverage
availableLanguage  Languages supported, the two letter codes are used in this instance.
contactOption  Used to indicate further contact options: a free telephone number or support for hearing-impaired.
contactType  Used to specify the business contact area: sales, support.
email  Email address
faxNumber  Fax number
hoursAvailable  The opening hours whilst the contact is available.
productSupported  If the organisation wishes to highlight that these support details are for a particular product line or area.
telephone  A Telephone number

Looking at the table above it can be seen that the opening hours for the organisation can be wrapped to highlight the timing.

There’s a lot of different properties on the Schema website. Spend some time looking around to find the best match between the type of businesses and the information which you wish to convey.


I wanted to use contact details, telephone and email which weren’t genuine or likely to be. In the references I’ve included a link to Ofcom’s numbers for drama. A list of numbers which won’t be assigned, much like the use of example.com for domains and email addresses in documentation.

Schema address


Ofcom: Numbers for drama

Scroll Page on Page Load

On loading a web page scroll to the top of a form.

I had a web page with a form, part of a sequence of pages. Rather than the user scrolling down to the start of the form, I scrolled the page to the start of the form on page load.

Or more specifically to scroll to just above the top of the form on page load. Giving a degree of orientation reference within the page.

Above the form I added a div with an id:

<div id=”FormTop”></div>

Within the header (or separate JavaScript file if preferred) add the entry to scroll the page.

  $('html, body').animate({scrollTop: $('#FormTop').offset().top}, 'slow');

Shown above is the animation, associated with either html or body. Here the scrollTop function moves the page to the FormTop ident, at a speed set as slow. Once the page has completed loading and is ready.

Perhaps the scroll isn’t to your liking. Both the speed and the flow (easing) of the scroll can be changed.

Other speeds can be used, try experimenting with these (in milliseconds):

$(‘html, body’).animate({scrollTop: $(‘#FormTop’).offset().top}, ‘500’);

The easing effects used for the animation can also be added, for example:

$(‘html, body’).animate({scrollTop: $(‘#FormTop’).offset().top}, ‘slow’, ‘swing’);

Linear is an alternative. This specifies how the path of the animation flows. There are more available by incorporating the jQuery UI script.

No doubt when you implement this you’ll add the single action line along with the rest of your items within $(document).ready(function(), not give its own distinct wrapper.






Bootstrap3 Removing Parent Menu onClick

Using the Bootstrap menu clicking on a parent menu item reveals the child items. The parent page isn’t opened in the traditional menu way.

This is by design.

In summary, clicking on the parent menu item shows child menu items as drop down
Hovering over the parent page has no effect.

The result which I wanted was:

Hover over parent menu item to show child menu items in a drop down
Click on parent to change page, showing parent page.

The onclick of the parent menu item causes a drop down to appear and not to move forward to view the parent item

Changes to be made

  • onclick to open parent item
  • hover to show dropdown

To implement the changes I removed the data-toggle attribute and added a hover function emulating the click action but adding the open class.

I added the following to the header.php file of the WordPress child theme.

<script type="text/javascript">
var $vntweb =jQuery.noConflict();
$vntweb(document).ready(function ($vntweb) {
	$vntweb('a').removeAttr( 'data-toggle');
	$vntweb('.dropdown').hover(function() {

A better place to add this would be an included JavaScript file.

I like to add my own variable $vntweb with a noConflict, rather than simply the use of $. Usually this keeps me out of trouble, avoiding conflicts with other uses of $ as a variable


Reset WordPress Metabox Positions

Viewing a WordPress page, post or custom entry

Having moved the sections around how do I reset.

Reset WordPress metabox positions: view post

The idea is how to restore the edit view of

Whilst developing a recent plugin I had moved the meta box sections around. But, of course, I wanted to see the default. As per a fresh installation.

So how do I reset the layout of the displayed WordPress displayed content area sections?

For this approach you’ll need access to phpMyAdmin via your hosting control panel.

The relevant saved options in the database table wp_usermeta are to be deleted.

Login to phpMyAdmin to begin.

Reset WordPress metabox positions: phpMyAdmin

In the left hand database & table menu click on the database for the WordPress website of interest.

From the top row of tab options click on SQL.

Reset WordPress metabox positions: phpMyAdmin SQL

The content entry box can be used to enter the SQL which will be used to show the specific entries in the wp_usermeta table.

wanted to reset the metabox positions after moving them round

In you PhpMyAdmin query for: (if you have a different database prefix, change that in the query, also change the user_id to yours)


FROM  wp_usermeta
WHERE  user_id =1
AND  meta_key LIKE 'meta-box%'


Click on Go in the bottom right corner.


Reset WordPress metabox positions: phpMyAdmin SQL usermeta


Look at the meta_key column to determine which plugin, theme, post or whatever the entry is associated with.

Delete those values which are associated with the item which you are looking to reset, and you will get the original order back.

Easy –  I simply deleted the relevant one.

And the user id> Well its a development website on a development computer with the initial user as my admin login. So no problems there with knowing the value.

But this is cumbersome. You need to know the relevant user id. It would be better to use the user name.

This is easier to find and has less chance of making changes to the wrong account.

For this we’ll modify the SQL using a join to combine the two tables of usermeta and users.

FROM wp_usermeta
JOIN wp_users ON wp_usermeta.user_id = wp_users.id
WHERE wp_users.user_nicename ='neil'

As previously change the relevant parts.

In this example we’ll show all items in the usermeta table, as before. The third row shows the join with the users table. With the linkage by the associated user id.

The last line is the restrictive clause, this time using the displayed name of the user.

With a little SQL and the use of phpMyAdmin we are able to delete entries in a WordPress table, resetting the order of the metaboxes from a plugin, page or post.

WordPress Redirect to https

Your WordPress website was running as a traditional unsecured site.

Now to meet the search engine guidelines you have added a certificate and encrypted the website.

But the old unencrypted website address is still accessible.

This isn’t good for SEO with effectively two websites with the same content.

How to redirect the unencrypted traffic to the encrypted website address.

We’ll add the redirect to the .htaccess file found in the root of the website.

Shown below is the default entry in the .htacces file

# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]

The additional redirect rule to be added is:

RewriteCond %{ENV:HTTPS} !=on
RewriteRule ^.*$ https://%{SERVER_NAME}%{REQUEST_URI} [R,L]

And here it is the updated version, with the additional redirect rule added.

# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteCond %{ENV:HTTPS} !=on
RewriteRule ^.*$ https://%{SERVER_NAME}%{REQUEST_URI} [R,L]
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]

The content of the .htaccess file may be amended via the hosting control panel or via FTP.

You may wish to take this amendment as a prompt to take a backup of your website files.

Insert string into Database as datetime

Inserting values into a database table I wished to add a date and time.

For this I used a convert

CONVERT(datetime, ’26/05/2014 14:21:00′)

However this will fail where the day value is too high. A value greater than 12 will be taken as an invalid month. Also the day and month will be saved swapped.

The date format should be defined as UK based, d/m/y

For this the country format value is included within the conversion.

CONVERT(datetime, ’26/05/2014 14:21:00′, 103)

In this example using 103 to handle UK date format

Note: also ensure there are no spaces at the start or end of  the enclosed string.