Are you an existing customer?

I suspect that most store owners would like their customers to purchase more than once – I know that I like people to purchase my products as often as possible!

I’ve never really explored the avenue of “returning customers” to any great degree. My idea this morning is to optimise the checkout (covered in a previous post!). A quick summary:

1. person presses “pay now” (aka checkout)
2. they go to account creation page (rather than the login page) – I feel that the account creation page is less “in your face” that a login page.
3. They create an account and checkout as normal.

Now, my idea is to set a lifetime cookie in the “create_account” process. This cookie will simply show that the person using the computer has already created an account. The next time that they come to buy something from the shop, the cookie will get read and instead of the “pay now” redirecting to “create_account”, it will redirect to “login”…

Note that the cookie will hold no identifiable information such as email address or password etc – just a simple falg to say whether or not an account has been made already.

Does anyone see a downside to this idea?

Let’s see what we have here

“Let’s see what we have here” – a piece of text that shows as the title in each of your category pages. Absolutely useless! You should change this to something more interesting and useful (in terms of user experience and SEO) such as the title of the category – doing this is very simple…

Open up /includes/languages/english/index.php and find:

[php]define(‘HEADING_TITLE’, ‘Let\’s See What We Have Here’);[/php]

Change to:

[php]define(‘HEADING_TITLE’, $categories[‘categories_name’]);[/php]

Save and upload. Done.

There is a slight problem once you’ve done this, but I’ll cover that in a future post – inthe meantime I wonder if any of you can work out what the problem is? The first person to spot the problem and present a solution will win a prize…

Answer to Problem:

[php]$category_name = (isset($HTTP_GET_VARS[‘manufacturers_id’])) ? $manufacturers[‘manufacturers_name’] : $categories[‘categories_name’];
define(‘HEADING_TITLE’, $category_name);[/php]

manufacturers are now called as appropriate.

Clear Cart, then add a product automatically

Frank asks;

I’m trying to create a page that when someone visits; automatically empties the shopping cart and then adds one specific product, so the cart will only have that one item whenever the customer loads that page.

I thought this was an intelligent and interesting question – and as no-one else was helping, I decided to post it here in the blog rather than in the osCommerce Forum.

The Solution

My idea for this is to create a standalone page which you can advise your customers of – this page will simply do the following;

  • Clear the Cart Contents
  • Add a product to the Cart
  • Redirect to the Shopping Cart Page

That’s fairly straightforward and should just about cover what is needed.

How To Do It

1. Create your product – this will simply be the product that you want added to the Cart. Easy enough. Make a note of the Product ID – as we’ll need this in our “adding” code!

2. Create a new blank file called “addproduct.php” and save it into the same directory as your normal base files (index.php, product_info.php and all the rest). You can name it whatever you want really.

3. Add the following code to the file you created in Step 2:

tep_redirect(tep_href_link(FILENAME_SHOPPING_CART, ”, ‘SSL’));

In this example, the Product ID is “28” – you can see this in the second $cart line. Amend this number to whatever Product ID you are going to use.

4. Save the file. Visit in your browser and you will end up at your site Shopping Cart, with nothing other than Product ID 28 (or whatever ID you used!) in the Cart.

Easy as 123. Can I get a “hell yeah”?

What if your product has “options” (aka attributes)?

That’s a bit more problematic, but not overly so. What you will need to do is create your Product, with all it’s options. Then visit the product and add it to your Cart (making sure you selected the options that you wish your customers to automatically add) and view the resulting URL to get the options values… sounds complicated, so;

Let’s illustrate this with an example

In a standard install of osCommerce, Product ID #1 is a Matrox G200 MMS with a couple of options. Let’s say that that you wanted the following to be added to the cart automatically:

A “Matrox G200 MMS” with “Memory of 16Mb” and “Model Premium”. Select these options and press “add to cart” button. This will now show your Shopping Cart with the product and it’s options. Copy the link back to the product, and paste it somewhere – you will see something like this:{4}3{3}6

Those numbers in brackets are the options that we selected! So…now you have this, you need to go back to the addproduct.php code and amend it slightly, like this:

$cart->add_cart(1, 1, array(4 => 3, 3 => 6));
tep_redirect(tep_href_link(FILENAME_SHOPPING_CART, ”, ‘SSL’));

Look at the difference in the 2nd $cart line – you can see a couple more parameters – they work like this: add_cart(PRODUCT ID, NUMBER OF PRODUCTS TO ADD, OPTIONS)

In the options part, you can plainly see a correlation between the URL we copied: product_info.php?products_id=1{4}3{3}6 and the option value: array(4 => 3, 3 => 6)

So, adding options make things slightly more complicated, but not overly so.

I have no doubt that in practice, this will need tweaking, but at least you now have a start in a way (maybe not even the best way!) to do this. Go to it!

Finding Text that you want to change

osCommerce is set up a little differently to a “normal” website.  Put simply, this is because the “base pages” are the structure and “language pages” are pulled into the structure automatically.

  • index.php
  • product_info.php
  • and all the rest of the pages

are your “structure pages” – these should only be amended if you are adding contributions or changing the actual design of your site.

Your “language pages” reside 3 levels “down”;

  • /includes/languages/english/index.php
  • /includes/languages/english/product_info.php
  • /includes/languages/english/conditions.php
  • and so on…

Can you see the relationship between the “structure page” and the “language page” ?

  • conditions.php => /includes/languages/english/conditions.php
  • and so on…

In other words, the TEXT for “your “Terms and Conditions Page” (conditions.php) is all contained in the following file:  /includes/languages/english/conditions.php

The same for “contact_us.php”, “index.php” and so on.

However, there are a few exceptions!

You need to be aware of the fact that some TEXT is contained in MULTIPLE files (eg, the text in the footer of each page).  Using the above file by file method, this would mean that we would have to repeat the same information many times (for it to show on each individual page).  So we have one more OVERALL language page called “english.php”.  It is located at /includes/languages/english.php

SO…whenever you are looking for text to change, the first place that you should look is in the individual language page and then in the overall “english.php” page.

If you can remember that MOST text is either contained in the INDIVIDUAL language file (always inside /includes/languages/english/*.php) OR in the OVERALL language file (always /includes/languages/english.php) you won’t go far wrong.

NOTE:  If you don’t use “english”, then look in the folder that you do use, eg:  /includes/languages/german/*.php … and the OVERALL german file at /includes/languages/german.php

That wasn’t so difficult, eh ?

Random Products on Front Page

Almost daily, I see this question asked in the osCommerce Forum…

How can I have 9 random products showing in the the “New Products For…” box in the front page of my osCommerce site?

The answer is really, really simple – you need to change the SQL that selects the 9 products, like this;

Open up /includes/modules/new_products.php


[php]p.products_date_added desc[/php]

Change to:


Upload the file and refresh your index page. You’ll get 9 random products rather than the last 9 added/amended products. A better option in my opinion would be to add a “Featured Products” contribution, as I think that no customer wants to see Random Products.

Updated for ’08 – Make Your osCommerce Faster

I just finished up the next osC Book update – ‘How To Make Your osCommerce Faster‘ – in this eBook I show a number of methods that will speed up your osCommerce store.

speed_up_oscommerce.jpgSome of the changes are very simple, some are more advanced. This morning, I installed a brand new osCommerce RC2 and managed to get the page load time down from 1.375 seconds to 0.563 seconds with just a few cut and paste changes and a couple of Admin changes – that’s a page load speed decrease of just about 59% – and that is on a standard installation of osCommerce – if you have a larger osCommerce store, you should see even more startling results!

In addition to the excellent speed increase, the changes mean less calls to the MySQL database which is always a good thing.

The contents of the eBook is very easy to follow and I can say for sure, that even if you only make a couple of the changes in the eBook, your store will run faster and smoother.

So, if you want to make your osCommerce speedier – and therefore more pleasing to your potential buyers, have a think about purchasing the eBook – you might just learn something you didn’t know before.

And the price is set at just £3.99 (about $7) – not too much to pay for a more pleasing website I’d say.

Reversing the order of the cart contents

In the osCommerce forum, someone posed an interesting question;

does anyone know how to reverse the order of the shopping cart dsiplay so that new products added will go onto the top of the list rather than the bottom.

Having thought about the question for a minute or two, this actually makes perfect sense and makes any shop more useable in my opinion. After all, if a customer has 20 items in their cart, it makes sense not to make them scroll to see the last item added.

So, how to do this?

The user in the osCommerce forum posted some code she had made – but it was problematic – and it’s no point posting broken code here. My solution is ALWAYS to go for the easiest way to do something…

Open up /includes/classes/shopping_cart.php and find;

[php]return $products_array;[/php]

Change it to;

[php]return array_reverse($products_array);[/php]

Save the file, upload and test your new look shopping cart 😉

REMEMBER: always try to do things the easiest way possible. If you make things easy, it’s just as easy to go back to standard osCommerce when (if) it all goes wrong!

Did this help you? Feel free to buy me a beer 😉

Just a few products? Dump the categories…

Years back I had a client who had only a few products in his store. Rather than use the category infoBox I rewrote it to simply give a direct link to each product.

It’s funny that I was looking at that store the other day (it’s on the Hot 100 list), and today someone in the osCommerce Forum asked for exactly the same thing.

Rather than try to find the file I used on that old site, I just rewrote the script. 2 minutes later, and here we are;



new infoBoxHeading($info_box_contents, false, false);

$products_list = ‘


$info_box_contents = array();
$info_box_contents[] = array(‘text’ => $products_list);

new infoBox($info_box_contents);


What this script will do is simply list all your products in a long list, instead of the category box. Easy as 123, eh?

Obviously if you use this script, you will need to set a style on the <ul and maybe the <li – depends upon what you want the list to look like 😉

Passing $cPath thru Advanced Search…

In the official osCommerce Forum, someone asked for the ability to pass the $cPath variable through the Advanced Search Result “link” for each product.

Basically, instead of a direct link to a product, eg: product_info.php?products_id=10, he wanted product_info.php?cPath=3_11&products_id=10

The example obviously assumes that Product 10, is inside Subcategory 11 which is inside Category 3. Got that 😀

The code changes are minimal. There’s only two files to change and it goes like this:

advanced_search_result (about line 207)

Find this:

$select_str = “select distinct ” . $select_column_list . ” m.manufacturers_id, p.products_id, pd.products_name, p.products_price, p.products_tax_class_id, IF(s.status, s.specials_new_products_price, NULL) as specials_new_products_price, IF(s.status, s.specials_new_products_price, p.products_price) as final_price “;

Change to:

$select_str = “select distinct ” . $select_column_list . ” m.manufacturers_id, p.products_id, p2c.categories_id, pd.products_name, p.products_price, p.products_tax_class_id, IF(s.status, s.specials_new_products_price, NULL) as specials_new_products_price, IF(s.status, s.specials_new_products_price, p.products_price) as final_price “;

/includes/modules/product_listing.php (about line 90)

Find this:

for ($col=0, $n=sizeof($column_list); $col<$n; $col++) {
$lc_align = ”;

Right below it, add:

if (tep_not_null($listing[‘categories_id’])) {
$cPath = tep_get_product_path($listing[‘categories_id’]);

Done!  Save the files, upload and test the product links.  Feel free to Paypal me a donation if you find it useful 😉

MySQL Server DOWN – oh no!

In the official osCommerce Forum I got into bit of a conversation with a Store Owner, part of the conversation was all about what happens if your MySQL server goes down whilst the webserver is still up and running.

For those who don’t know, MySQL runs on it’s own little server as part of the overall web server.  So it is possible for one to be down whilst the other is functioning OK…

OK, so, in a standard osCommerce shop, what will happen is that a message will be displayed, like this:

Unable to connect to database server!

Which isn’t so great for anything – after all, it is your CUSTOMERS who will see this!  So, my idea was to make this message a little better for you and your customers.

Open up the file /includes/application_top.php and find

tep_db_connect() or die(‘Unable to connect to database server!’);

This line of code is simply saying “Connect to the Database OR kill the connection and show the “unable to…” message.  We are going to change this line of code to;

@tep_db_connect() or header(“Location: busted.html”);

Now we are saying “Connect to the Database OR redirect to a page called busted.html”.  Easy, eh?  Notice that we also put an “at” (@) sign in front of tep_db_connect – this is important as we wish to make sure we suppress any other error messages.

Save the /includes/application_top.php file and upload it to your server to replace the old one (which you might like to backup first!).

The next step is to make a new HTML page called “busted.html”.  On this page you can have anything you like – maybe an error message, maybe a “contact us by phone” message – maybe something else entirely!

However, there is one VERY IMPORTANT CAVEAT – the “busted.html” page MUST NOT connect to your database!  As your database server is down, it would be completely pointless to do so.

Of course, the page can be .php if you wish and it doesn’t have to be called “busted.html” – it can be called anything you like.  Just make sure that the name fo the file and the “Location” line of code match exactly!

You could send yourself an error message by email, or you could even send a signal to the server to restart the SQL server (this would be for very advanced users who have control of their own server).  For most of us, a simple HTML page will suffice.

Why 404 redirect won’t work in this case

If your SQL server is down, pages are still presented by the webserver, so they do not 404 (error out) and redirect.  What this means is that you could go to; and see “Unable to Connect” – this is NOT a 404 and so it won’t redirect to an error page.   Does this make sense?