Archive for the 'Software' Category

July 5, 2011

OK, this one is a bit of an edge case, but I’ve dealt with similar issues while trying to set a static block through a template file when you need that static block to change based on the product being viewed.

Sure, it’s easy to call the static block in the product’s custom layout update, but the problem there is that you can’t place that block anywhere between the title and product description. All of those elements are called as childHtml and can’t be referenced by the layout XML. What happens if you need to put a special notice near the price or short description?

You could create a custom theme for each different product, but that could lead to a maintenance nightmare when you need to update a product page. You could also create a custom block and template, but that takes a lot of effort.

We’ll start by looking at calling a static block in the template file. It’s fairly academic to add the static block in the template’s phtml code in Magento:

<?php echo $this->getLayout()->createBlock('cms/block')->setBlockId('my_static_block')->toHtml() ?>

This works great, but every product page will have the exact same static block.

In this particular case, I needed to add some pricing information based on the product’s SKU. For simplicity I’ll say the SKUs were 1, 2, and 3. In this case, I created a static block for each of the three pricing notes, and set the identifier to product1, product2, and product3 respectively.

Magento Dynamically Set Static Block From Template

Now, in the template file, I’ve changed the way the setBlockId is called:

<?php echo $this->getLayout()->createBlock('cms/block')->setBlockId('pricing'.$_product->getSku())->toHtml() ?>

This way the setBlockId would change depending on the product SKU. In theory this can also be done with custom attributes or any other product value. As an added bonus, it fails gracefully if it encounters a static block that doesn’t exist. Say for SKU = 4 I haven’t created a static block, so on that product page, no extra html is generated and no errors occur.

As I said, it’s a bit of an edge case, but it might come in handy in that rare instance.

June 21, 2011

Magento is a great tool, but sometimes adds some unnecessary friction to the buying process. Take Custom Product Options drop-down list for example. There is no way to set an option as a default.

If you have several custom options on a product, but 80% of the customers are buying a certain option there is no point in making those customers actually choose the option from the list – it should be set by default.

There is a relatively easy fix for this one.

CAUTION::To do this requires editing of one of the Core Magento files. If you upgrade your Magento version, it will overwrite this code. Also, this will apply to all Product Custom Option Drop-down lists on your site.

This example is based on Magento 1.4.2.0. so the exact location in the file may be different if you are running a different version.

First make sure you set the most popular option to the first in the sort order on your Custom Options tab. Now you want to fine the file app/code/Mage/Catalog/Block/Product/View/Options/Type/Select.php. Look for the following code (in 1.4.2.0 it starts on line 52):

if ($_option->getType() == Mage_Catalog_Model_Product_Option::OPTION_TYPE_DROP_DOWN) {

$select->setName('options['.$_option->getid().']')

->addOption('', $this->__('-- Please Select --'));

You’ll want to edit out the line that calls for the addOption():

if ($_option->getType() == Mage_Catalog_Model_Product_Option::OPTION_TYPE_DROP_DOWN) {

$select->setName('options['.$_option->getid().']') ; //<- don't miss this semi-colon

// ->addOption('', $this->__('-- Please Select --'));

That’s it! Now refresh your browser and your Custom Option Drop-down should default to the first option in the sort order.

March 13, 2011

With the delivery of a number of successful line of business applications built with the Microsoft ASP.Net MVC 2.0 architecture we thought it was time to blog about our view of the framework versus traditional web forms. Both the Foundtastic web app for the City of Edmonton Transit department and the DOC-IT/SAMPLE-IT system in use at the Wood Buffalo Environmental Association (WBEA) are excellent examples of custom web solutions leveraging ASP.Net MVC 2.0. In the case of the latter example a multi-million dollar scientific research operation is managed through the powerful DOC-IT/SAMPLE-IT web app. There are 3 significant improvements MVC brings to web app development for Microsoft environments: powerful client-side scripting, performance and testability.

Brief Introduction to Microsoft ASP.Net Model-View-Controller (MVC) 2.0

The Model-View-Controller pattern has been around for over three decades. It has been adapted for use in several user-interface frameworks. It is a very simple pattern that advocates the clear separation of responsibilities between the model (data), controller (logic & orchestration) and the view (presentation). It has been observed to help produce more maintainable, structured applications. Web Forms and ASP.NET MVC differ radically in their adherence to separation of concerns best practices.

jQuery & client-side scripting

In the early days of Web development, client-side script was mostly relegated to tasks such as validation. With the advent of Ajax this changed and a lot of complex JavaScript was written to create AJAX-enabled Web applications. This was tedious, complicated and error-prone work. Client-side scripting has a reputation for being quirky and difficult to get right. IDE support for the JavaScript language was lacking until recently. The language itself, while very capable, was not understood very well. The Document Object Model as implemented by different browsers caused several compatibility issues and generally earned its name as a difficult area to get right.

Over time, frameworks emerged to make this work easier. One such framework that emerged, and has quickly become the de facto standard for authoring client-side functionality, is the jQuery4 framework. jQuery makes it quite easy to work with client-side script. It abstracts away differences between common browser platforms and offers an elegant CSS-like syntax for targeting elements of the DOM. This, coupled with its fluid interface, has made client-side programming a joy.
The Web Forms framework and the ASP.NET MVC framework differ substantially in their ability to work seamlessly with jQuery.

Performance

The ASP.NET MVC Framework allows for very lightweight markup. The application of unobtrusive JavaScript principles also leads to less markup being produced since it avoids repetitive inline markup such as that used for event subscriptions. Any state maintained by an MVC application is targeted and usually a small fraction of ViewState on similar Web Forms pages.

Performance differences are even more pronounced with Ajax applications. With Web Forms, the entire page lifecycle with all its associated traffic/code is required. This leads to much higher traffic back-and-forth with the server.

Testing

Solid and easy testing of business logic and data access is considered to be critical to the development of maintainable Web applications. Web Forms applications are very hard to test. This is primarily due to the following reasons:
• It remains hard to automate Web Forms applications without running them inside a complete hosting environment. It is not possible to easily simulate a complex hosting environment such as IIS.
• The view often contains business logic and presentation, making it very hard to test the business logic without testing the presentation.

In practice this meant that Web Forms applications were usually tested using elaborate UI automation tools or manual testing – an error-prone and expensive process.

ASP.NET MVC makes testing easy alleviating many of Web Forms barriers. All of the core components of ASP.NET MVC are designed to easily run from any unit testing container. Furthermore, the entire MVC application is compiled within the Visual Studio development providing early indication of errors and problems.

I’ll be writing about deploying an MVC web app to the Microsoft Azure platform in an upcoming blog!

References:
Microsoft Developers Network
http://msdn.microsoft.com/en-us/
IEEE – ACM
http://portal.acm.org/citation.cfm?id=1088812

October 17, 2010

Magento as a CMS Tool

Magento continues to be one of the best shopping cart solutions in the market space. Although the architecture can be confusing and frightening at times, it is very powerful once you know how to use it. From merchandising your products, to exceptional SEO, all it takes are small adjustments to make your Magento implementation soar.

On many eCommerce sites, the content pages aren’t considered in the overall merchandising strategy. When used correctly, they can provide a wealth of product information, drive SEO results and therefore increase revenues. At first glance, Magento’s CMS pages look like they are just there to manage Terms and Conditions and some brief “About Us” content, so many merchants reach for other tools like WordPress to handle their content.

However, by using the URL rewrites, Static Blocks and a little extra work, Magento can render some rich, categorized content very effectively.

Magento CMS Pages

The first step to making this happen is in the creation of a new content page. Go to CMS->Pages and click on “Add New Page”.

The first thing that happens is you are prompted to input a Page Title and URL Key. Most often users enter a copy of the  page title in the URL Key, changing CAPS to lower case and replacing spaces with hyphens.

But Magento allows for just about any valid URL string you want to put in there. So, you can create content that is ‘category/sub-category/page-title’

Using this method, you can create content in any sub-category you choose.

Magento Static Block Driven Menu

Now that we have categorized content, the next step is to create a menu that links to these content items. This is easily accomplished using static blocks to create the menu lists, then by pulling those lists into the layout as required.

You can use a single block for all of your categories, but you might find it provides more flexibility to create a static block per main category. Either way, the process is essentially the same.

Start by creating a new static block: CMS->Static Block and click on “Add New Block”.

Choose the category, or menu name, you want this static block to control as the Block Title. Use something descriptive for the Identifier. You can also leverage URL rewrites if you want have a multi-lingual shop and effectively switch between languages. (see our article on setting up multi language content in Magento).

Although the WYSIWYG editor in Magento 1.4.x is an excellent addition, I’d recommend using the HTML view for this. Add the nested list of categories, sub-categories, sub-sub-categories, etc as follows (assuming the static block is for a Category):

<ul>
<li><a href="{{store direct_url="category/sub-category1"}}">Sub-Category1</a></li>
<ul>
<li><a href="{{store direct_url="category/sub-category1/sub-sub-category1"}}">Sub-Sub-Category1-1</a></li>
<li><a href="{{store direct_url="category/sub-category1/sub-sub-category2"}}">Sub-Sub-Category2-2</a></li>
</ul>
<li><a href="{{store direct_url="category/sub-category2"}}">Sub-Category2</a></li>
<ul>
<li><a href="{{store direct_url="category/sub-category2/sub-sub-category1"}}">Sub-Sub-Category2-1</a></li>
<li><a href="{{store direct_url="category/sub-category2/sub-sub-category2"}}">Sub-Sub-Category2-2</a></li>
</ul>
</ul>

You can pull this static block into your design by calling the static block in the tempate. You will likely set up the menus in the header.phtml file for example, so you would add a line such as:

<?php echo $this->getLayout()->createBlock('cms/block')->setBlockId('category')->toHtml() ?>

Use your favorite .css or .js technique to expand the menu if you’re putting it in a horizontal menu, or just let it fly as a tree list in the margin. You now have some easy-to-navigate and nicely organized content on your site. Not to mention the search engine optimization lift you’ll get out of having the category descriptor in the URL.

September 2, 2010

Add the Google Analytics Tracking Code

OK, this part is really easy. Once you’ve signed up for your Analytics account, Google will give you a tracking code. It will be a number that looks like “UA-xxxxxx-x”. Copy this tracking code.

Log in to your Magento admin panel. Go to System -> Configuration. In the left hand menu, click on the “Google API” tab under the Sales heading and open the Google Analytics accordion menu. Set Enable to “Yes” and paste the Google tracking code in the Account Number field.

Magento Google Analytics Tracking Code Setup

Click “Save Config” at the top right and you’re done.

Top or Bottom?

If you’ve ever checked you may notice that the Google Analytics tracking code was typically placed at the bottom of the page, just before the </body> tag. If you’re running Magento 1.4.x.x, you may notice that the analytics code is now placed right at the top of the page.

Google’s original code looked like this:

<!-- BEGIN GOOGLE ANALYTICS CODE -->

<script type="text/javascript">
//<![CDATA[
var gaJsHost = (("https:" == document.location.protocol) ? 
"https://ssl." : "http://www.");
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js'
 type='text/javascript'%3E%3C/script%3E"));
//]]>
</script>
<script type="text/javascript">
//<![CDATA[
var pageTracker = _gat._getTracker("UA-xxxxxxxx-x");
pageTracker._trackPageview("/");
//]]>
</script>
<!-- END GOOGLE ANALYTICS CODE -->

The old code could slow down the pageload time while Google loaded some fairly hefty javascript libraries to handle the analytics tracking. While the library downloaded, nothing else could happen on the page. Slow page load times make for bad user experience, and with Google’s recent changes in it’s Page Rank algorithms, page load times have an impact on SEO. By placing the code snippet at the bottom of the page, it would ensure that the analytics library was the last thing done on the page.

One concern with this method was that if a user bounced or otherwise left the page before the library downloaded, then any tracking of that event was lost.

Google recently changed the javascript code snipped to utilize ajax to asynchronously handle loading the libraries. This means that the time to load the library is no longer a factor. Google’s new best practices suggest that the code snippet should be added close to the top of the page so that all page events will be captured no matter how fast the user reacts.

Google’s new ajax code snippet looks like:

<!-- BEGIN GOOGLE ANALYTICS CODE -->

<script type="text/javascript">
//<![CDATA[
    (function() {
        var ga = document.createElement('script'); ga.type = 
'text/javascript'; ga.async = true;
        ga.src = ('https:' == document.location.protocol ? 
'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
        (document.getElementsByTagName('head')[0] || 
document.getElementsByTagName('body')[0])
.appendChild(ga);
    })();

    var _gaq = _gaq || [];
    _gaq.push(["_setAccount", "UA-xxxxxxxx-x"]);
    _gaq.push(["_trackPageview", "/"]);
//]]>
</script>
<!-- END GOOGLE ANALYTICS CODE -->

Configuring Analytics Code in Magento

If you are inclined to update Magento 1.3.x.x to the new asynchronous code snippet or want to move the code snippet around the site, there are two files you’ll want to concern yourself with.

Change the old ga.js Code to the Asynchronous

The first is the code snippet itself. It is located in ‘/app/code/core/Mage/GoogleAnalytics/Block/Ga.php’. You will want to find the _toHtml() method and look for:

$this->addText('
<!-- BEGIN GOOGLE ANALYTICS CODE -->
<script type="text/javascript">
//<![CDATA[
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
document.write(unescape("%3Cscript src=\'" + gaJsHost + "google-analytics.com/ga.js\' type=\'text/javascript\'%3E%3C/scri$
//]]>
</script>
<script type="text/javascript">
//<![CDATA[
var pageTracker = _gat._getTracker("' . $this->getAccount() . '");
pageTracker._trackPageview("'.$this->getPageName().'");
//]]>
</script>
<!-- END GOOGLE ANALYTICS CODE -->
');

You can update that code to:

$this->addText('

<!-- BEGIN GOOGLE ANALYTICS CODE -->

<script type="text/javascript">

//<![CDATA[

(function() {

var ga = document.createElement(\'script\'); ga.type = \'text/javascript\'; ga.async = true;

ga.src = (\'https:\' == document.location.protocol ? \'https://ssl\' : \'http://www\') + \'.google-analytics.com/ga.js\';

(document.getElementsByTagName(\'head\')[0] || document.getElementsByTagName(\'body\')[0]).appendChild(ga);

})();

var _gaq = _gaq || [];

_gaq.push(["_setAccount", "' . $this->getAccount() . '"]);

_gaq.push(["_trackPageview", "'.$this->getPageName().'"]);

//]]>

</script>

<!-- END GOOGLE ANALYTICS CODE -->
');

Change the Location of the Code Snippet on the Page

Once that is updated, you can change the position of the code snippet on the page by modifying the ‘/app/design/frontend/base/default/default/googleanalytics.xml’ file (or in the correct sub-directory for your template if applicable).

Look for the following code:

<reference name="before_body_end">

<block type="googleanalytics/ga" name="google_analytics" as="google_analytics" />

</reference>

and change “before_body_end” to “after_body_start” to move the code snippet to the top of the page.

Magento Multi-Language CMS

Author: Geoff Kliza
August 9, 2010

The problem: no language settings in Magento’s CMS pages causes 404 errors

If you are developing or planning to develop a multi-lingual site in Magento, you may have noticed that there are no language settings in the CMS content pages. You can select the store view where the page will display and have different content pages show up in each view of the store, , say one called ‘english-content-item’ enabled only for the English view and called ‘french-content-item’ enabled only for the French view. Using static blocks and different templates for each language you can make this work.

For example, we have some English language menu links in a static block called ‘header_links’ with a list of menu items pointing to the English content pages , and we have some French language menu links in a static block called “header_links_fr’ with a list of menu items pointing to the French content pages. We would modify the template/page/html/header.phtml file in our English view template with the following code:

getLayout()->createBlock('cms/block')->setBlockId('header_links')->toHtml() ?>

and the French view template with the following code:

getLayout()->createBlock('cms/block')->setBlockId('header_links_fr')->toHtml() ?>

That’s pretty straight forward, but here’s the rub. If you are in the English content item and switch to the French language, you’ll get a 404 error. The reason for this is that the URL in the English view is http://yoursite.com/english-content-item, for example. When you switch to the French language, the URL is http://yoursite.com/fr/english-content-item.

Since the ‘english-content-item’ isn’t enabled for the French store view, you get a 404. This is unlike the product pages, which can have separate content defined per store view.

The solution: URL rewrites to the rescue

The solution to Magento’s lack of multi-language CMS is to use the built in Catalog URL Rewrites under Catalog->URL Rewrite Management. By using permanent 301 redirects, not only can you avoid the 404 errors, but you can keep the URLs specific to each language – that’s good SEO!

In the URL rewrite manager, you’ll want to click on Add URL Rewrite and select “Custom” from the drop down list.

magento-url-rewrites

Under “Store” you will want to pick the first store, in this case we’ll start with the English store. “ID Path” and “Request Path” in the case of the CMS pages are going to be the same. In this case we want the French language site to properly redirect when switching to English, so we will use the “french-content-item” for the ID and Request paths.

Next we fill in the target path. In the case of the switch to the English site, we want it to redirect to “english-content-item”. We want it to be a 301 Permanent Redirect. You can add whatever description you need and Save.

Now, do the same for the French site, so use “english-content-item” for the ID and Request paths and “french-content-item” for the target path. Be sure select the French view under “Store”. Save that.

Of course, don’t forget to refresh your cache and make sure you re-index the catalog rewrites if needed. Now when you change languages on the front-end, the CMS page will switch to the appropriate page for you. No more 404′s and you get nice clean URLs, which means happy robots and better SEO results.

Magento Professional Edition

Author: Chad Smith
May 26, 2010

The recently announced Magento Professional Edition offers some exciting and useful new features for the online merchants, e-tailers and bricks and mortar retailers. Situated between the open-source Community edition and the feature rich Enterprise Edition, the new Professional Edition ships with some great revenue-generating, conversion improving features. This edition is a direct result of Magento incorporating customer feedback into its product line. We at Hybrid Forge think this is a brilliant move for Magento. Our experience with clients running Magento supports increased choice for licensed software.

Magento is a powerful, capable and flexible platform both from the technical feature set and site design perspectives. Magento’s use of an MVC framework makes the addition of conversion improving features cost-effective and reliable. This framework has allowed the 3rd party extension market to flourish as is evidenced by 2300+ extensions available via Magento connect. A div tag-based HTML layout affords skilled UX experts and graphics designers the UI malleability they require to bring novel and inspiring designs to life. The end result is intrinsically search optimized HTML output that is superlative to virtually all other eCommerce platforms. Magento demonstrates its commitment to supporting your growth by providing a direct and easy upgrade path to the Enterprise edition when the time is right.

Here are some of the great features available in Magento Professional Edition

Gift Cards and Gift Certificates

Your customers can buy physical (physical card mailed to recipient) and virtual (code provided via email to recipient) gift cards and gift certificates. Customers may include a optional personal message when purchasing, and recipients can then use the value to purchase items from your store.

Reward Points System

Reward Points functionality allows you, the online merchant, to implement customized programs designed to increase customer loyalty. Points may be awarded to your customers based on configurable exchange rates for transactions and promotions, as well as user actions such as contributing ratings and reviews, signing up for your newsletter and more.

Customer Store Credits

Store Credits can be created and tied to customer account. Orders can be refunded for store credit, Gift Cards can be redeemed to store credit, and customers can use the credit to purchase items during checkout. Store credits dramatically reduce the management challenges associated with tracking transaction in an external system.

Strong Data Encryption

Professional Edition includes the encryption and security standards in the Enterprise Edition which support PA-DSS standards and ensure that Magento is a fully secure solution.

Download the Magento Professional Edition Datasheet

Hybrid Forge – Magento Experts

Looking to maximize your conversions with Magento? Consider using layered navigation and our latest extension for your featured products. Call us today for more information.

Interested in re-platforming your eCommerce system to Magento? Call Hybrid Forge at (877) 663-6743 for a no cost preliminary assessment and quotation.

February 3, 2010

Hybrid Forge is pleased to announce that our solution to the City of Edmonton’s Leveraging Technical Expertise Locally (LTEL) Pilot Project was chosen as the best among 14 competing applicants. The city solicited proposals for an innovative solution to replace the Edmonton Transit Systems’ (ETS) lost-and-found management system. The city partnered with TEC Edmonton to develop this initiative to gain access to new technologies and products that haven’t been realized previously.

“This is an excellent opportunity for us, and we are excited about forging relationships with the City of Edmonton and TEC Edmonton” says Geoff Kliza, President of Hybrid Forge. “Our goal is to integrate business systems with emerging web trends such as social networking to provide a closer relationship between our clients and their customers.”

The solution proposed by Hybrid Forge encompasses a web-based application built using the Hybrid Forge BaseModel MVC framework. The BaseModel MVC framework provides the foundation for building user-friendly data-driven applications while providing key productivity improving features such as simplified inventory search, enhanced reporting and user authentication via enterprise directory. Novel features of the proposed lost-and-found application include barcode-scanning support and an API for integration with social networking sites like Twitter and FaceBook.

Link to the Press Release on the Edmonton of City Website

September 30, 2009

More often than we thought we’re receiving inquiries from clients regarding a Magento deployment that is not performing to the level they expected. In this business the responsiveness of a client’s website is extremely important. If the browsing experience is lousy potential customers are going to move on to a competitor.

The single most effective configuration item for enhancing the performance of Magento is moneyCrucial Hosting

If the site is intolerably slow potential shoppers will go back to the Google and pick the next vendor in the list for the product they are looking for. Typically, clients with the most challenging of these performance issues clients end up contacting the team Hybrid Forge for an assessment and a resolution. Since the Magento eCommerce platform is based on the MVC brilliance of the Zend Framework we know that its extremely flexible and powerful. However, with great power comes great responsibilities. In the rush to re-platform an existing eCommerce package such as ZenCart, osCommerce, AspDotNetStoreFront, etc to Magento we’ve seen some absolutely tragic hacks of this framework.

Some of the more disconcerting examples are modified files in the /app/code/core (broken upgrade), completely copied default design directories with only one or two modified files and modifications pinned to specific database version (pre-1.2.1). Let’s get this straight – the learning curve is steep and perilous and you’ll get what you pay for if you choose a firm with little verifiable experience. While assessing and resolving these challenges is good for our business I think we all agree the world be would be a better place if we could avoid Magento missteps in the first place. The work isn’t done when the software is launched either. There are a number of logging tables that will grow unchecked less you perform regular maintenance on the database. The latest culprit we encountered in a recent audit is the “report_event” table. This particular Magento deployment had been running for a few months and collected well over a 150,000 records in the “report_event” table. By truncating this table we immediately realized a 500% improvement in php page execution time. Let me say that again, by truncating this single table we reduced page load time by 5X!

The recent Magento Enterprise Whitepaper contains some very useful configuration insight. If you haven’t read it yet download the Magento Enterprise Edition Whitepaper on Methods and Best Practices for High Performance eCommerce today.

The processes Hybrid Forge has developed for deploying, maintaining and evaluating Magento installations is constantly evolving because Hybrid Forge subscribes to a philosophy of continuous improvement. However, there many common elements to each and every deployment and this post serves as a abridged guide to some of the key technical elements gathered from both personal experience as well as fellow Magento authorities.

Abridged Magento Linux Installation and Optimization

We tend to deploy Magento on Centos 5.3 running Apache 2.2.x, PHP 5.2.x and Mysql 5.x. One of the first tricks is that PHP 5.2 is not available in the standard yum repositories. In order to install PHP 5.2 you’ll need to download and install the remi repositories via rpm:

  1. wget http://download.fedora.redhat.com/pub/epel/5/i386/
    epel-release-5-3.noarch.rpm
  2. wget http://rpms.famillecollet.com/el5.i386/
    remi-release-5-7.el5.remi.noarch.rpm
  3. rpm -Uvh remi-release-5*.rpm epel-release-5*.rpm

Now download PHP 5.2 – don’t get tempted by the 5.3.x release of PHP. Magento, as of this post is not compatible with PHP 5.3 so save yourself the grief of rolling back the PHP version and just say no (for now).

  1. yum –enablerepo=remi install php-common-5.2.10-1.el5.remi
  2. yum —enablerepo=remi install php-5.2.10-1.el5.remi
  3. yum install gd gd-devel
  4. yum –enablerepo=remi install php-mcrypt-5.2.10-1.el5.remi
    php-xml-5.2.10-1.el5.remi php-devel-5.2.10-1.el5.remi
    php-imap-5.2.10-1.el5.remi php-soap-5.2.10-1.el5.remi
    php-mbstring-5.2.10-1.el5.remi php-mysql-5.2.10-1.el5.remi
  5. yum –enablerepo=remi install php-mhash-5.2.10-1.el5.remi
    php-gd-5.2.10-1.el5.remi

Install APC (Alternative PHP Cache)

  1. yum –enablerepo=remi install php-pear php-devel-5.2.10-1.el5.remi httpd-devel
  2. pear install pecl/apc
  3. echo extension=apc.so > /etc/php.d/apc.ini

Now open the /etc/php.d/apc.ini and consider adding the following:

  1. apc.enabled = 1
  2. apc.shm_size = 128
  3. apc.include_once_override = 1
  4. apc.mmap_file_mask = /tmp/apc.XXXXXX

One more setting to consider and that’s:

  1. apc.stat = 0

If stat is disabled APC will NOT check for updated versions of PHP files automatically. Apache must be restarted to check for PHP file changes. It is useful in production servers where PHP code is not changed frequently and offers an increase in performance.

Apache Configuration

The Mozilla Firefox Firebug Net tab and the add-on Y-Slow will reveal if apache is configured to both compress files and send expiry details to visiting browsers.

Enable Apache Content Expiration

Locate your httpd.conf and adding the following section. Feel free to modify the expiration lengths if that’s not consistent with your front-end update strategy. Pay particular attention to the .css file expiration.

  1. <IfModule mod_expires.c>
  2. ExpiresActive on
  3. ExpiresByType image/gif “access plus 1 month”
  4. ExpiresByType image/jpeg “access plus 1 month”
  5. ExpiresByType image/jpg “access plus 1 month”
  6. ExpiresByType image/png “access plus 1 month”
  7. ExpiresByType text/plain “access plus 15 day”
  8. ExpiresByType text/html “access plus 1 second”
  9. ExpiresByType text/css “access plus 1 day”
  10. ExpiresByType text/javascript “access plus 1 day”
  11. ExpiresByType application/x-shockwave-flash “access plus 1 day”
  12. ExpiresByType application/x-httpd-php “access plus 1 second”
  13. </IfModule>

Enable Apache Output Compression

  1. <IfModule mod_deflate.c>
  2. AddOutputFilterByType DEFLATE text/html
  3. AddOutputFilterByType DEFLATE text/plain
  4. <FilesMatch “\.(js|css)$”>
  5. SetOutputFilter DEFLATE
  6. </FilesMatch>
  7. </IfModule>

After changes are made to the apache configuration you’ll of course need to restart the apache daemon.

MySQL Configuration

Open the /etc/my.cnf file and review the cache settings for MySQL. In a well spec’d server hosting a product catalog of up to 10,000 products these settings are a good rule of thumb. Magento uses Innodb type tables so the size of the innodb_buffer_pool_size is highly correlated to improved performance.

  1. query_cache_type = 1
  2. query_cache_size = 64M
  3. innodb_buffer_pool_size = 256M
  4. thread_cache_size = 16
  5. table_cache = 512
  6. key_buffer = 32M

.htaccess

Along with the standard Magento rewrite conditions avoid duplicate content issues by redirecting non-www requests to the www.mydomain.com.

  1. RewriteCond %{HTTP_HOST} ^mydomain.com [NC]
  2. RewriteRule ^(.*)$ http://www.mydomain.com/$1 [L,R=301]

File permissions

Reset your file permissions by running the following commands in the root of the Magento installation:

  1. find . -type f -exec chmod 644 {} \;
  2. find . -type d -exec chmod 755 {} \;
  3. chmod o+w var var/.htaccess includes includes/config.php app/etc
  4. chmod 550 pear
  5. chmod -R o+w media

In order run Magento Connect you may need to TEMPORARILY loosen file permissions by executing these commands in the root of the Magento installation:

  1. find . -type d -exec chmod 777 {} \;
  2. find . -type f -exec chmod 644 {} \;

Clean Up Script

Download the Magento Cleanup Tool and schedule its execution. I wouldn’t recommend exposing it to the world as suggested in the Magento Wiki page however.

http://www.magentocommerce.com/wiki/groups/227/resetting_file_permissions

References for this Post

Magento Wiki

Do it your-selfers will appreciate the single best, almost biblical, reference for Magento server setup and optimization is the Crucial Web Hosting blog at http://www.crucialwebhost.com/blog/magento-commerce-install-guide/

June 4, 2009

Visitors to your eCommerce website will enjoy seeing a ‘mini cart’ while they shop around. A minicart is a smaller, stripped down version of their full shopping cart, typically placed on side panels or inside website headers. As a web designer, I am happy to take advantage of the Interprise Suite eCommerce (ISE) Skin Tokens for displaying a minicart inside my custom design skins [i.e., (!MINICART!) ]. But, I like to make some modifications to the default minicart display and I believe you might too.

There are a few CSS and Javascript workarounds I’ll discuss to get around having to edit any C#, because the minicart markup is generated directly by the ISE code-behind, and is not easily accessible without the need to recompile your code-base.

Notes on this example: I assume the reader to have an intermediate skill level for writing valid CSS and also manipulating HTML elements (DOM) with Javascript. In my example, I have used JQuery to traverse, manipulate, and edit some elements because it works great, it’s feature-rich, and appears to have no conflicts with ISE core Javascript libraries. You can use whichever Javascript package you prefer. You may also want to refer to a previous post: Creating Custom Design Skins for Interprise Suite.

The Generated ISE Minicart HTML Markup

By default, the minicart HTML generated by the ISE code-behind comes out looking like this:

  1. <table width=”150″ cellpadding=”0″ cellspacing=”0″ border=”0″>
  2. <tr><td align=”left” valign=”top”>
  3. <img src=”skins/Skin_1/images/minicart.gif” border=”0″><br>
  4. <table width=”190″ cellpadding=”4″ cellspacing=”0″
    border=”0″ style=”border: 1px solid #444444;”>
  5. <tr><td align=”center” valign=”top”>
  6. <a href=”p-1-product-abc.aspx”>Product ABC</a>
  7. <br>Qty 1&nbsp;$ 5.00<br/><br/>
  8. <a href=”p-2-product-xyz.aspx”>Product XYZ</a>
  9. <br>Qty 1&nbsp;$ 5.00<br/><br/>
  10. Sub Total: $ 10.00<br/><br/>
  11. <a href=”ShoppingCart.aspx”>
  12. <font color=”BLUE”><b>CHECKOUT</b></font></a>
  13. </td></tr>
  14. </table>
  15. </td></tr>
  16. </table>

And here’s how it ends up looking by default – not ugly, but a tad unattractive, in my opinion:

ISE Default Minicart

First the problems, besides the obvious markup errors like mixing “<br/>” with “<br>”:

  • We can’t easily make changes to the HTML because it is derived from the C# code-behind;
  • The output is in a table, not horrible, but the “align=center” on the table cell will need to be looked at; I like this kind of output to be aligned left or right;
  • The “<FONT>” tag… my, oh my; But it will be useful for us, see below;
  • There’s no ID or class associated with the minicart for targeting it with CSS;
  • When the shopping cart is empty, the minicart doesn’t show anything – no nothing. This may or may not be what you want but in my case, i’d like it to show “Your Shopping Cart is Empty” when there’s nothing there.

Implementing the Interprise Suite Minicart Tweaks

First, you’re going to want to put your minicart Skin Token inside a wrapper in your template files so you can properly target it with CSS:

  1. <div id=”miniCart”>(!MINICART!)</div>

Here is my snippet of CSS that targets the minicart. Granted, i’m using that <FONT> tag in a way that probably wasn’t imagined originally, however it allows me to do what I need in modern browsers.

  1. /* Mini Cart CSS */
  2. #miniCart table { line-height:1.1em; }
  3. #miniCart table tr td img, #miniCart table tr td br,
    #miniCart table table td a font b { display:none; }
  4. #miniCart table table tr td br { display:inline; }
  5. #miniCart table table td { padding-bottom: 5px; }
  6. #miniCart table table td a font { float:right;
    display:block; width:112px; height:22px;
    background:url(‘../images/button-checkout.gif’) no-repeat 0 0;
    cursor:pointer; }
  7. #miniCart table table td a font:hover
    { /* roll-over sprite background-position */}

Because the table cell align=”center” and table border are both inline, I can’t override it with CSS. So, i’m going to use JQuery. And i’m also going to use JQuery to add some text to the ISE mini-cart when the cart is empty. So, first you’ll need to ensure you include the JQuery libraries in the <head> of your ISE template file:

  1. <head>
  2. <script src="/skins/Skin_(!SKINID!)/js/jquery-1.3.2.js"
    type="text/javascript"></script>
  3. . . .
  4. </head>

Then, you can use the following Javascript to target the minicart:

  1. /* JQuery Mini-cart Update */
  2. $(document).ready(function () {
  3. $(“#miniCart table table”).css({‘border-width’ : ’0′});
  4. $(“#miniCart table table td”).attr({align : ‘left’});
  5. if ($(“#miniCart”).text() == “”) {
  6. $(“#miniCart”).append(“<p>Your Shopping Cart is Empty.</p>”);
  7. };
  8. }

You’ll have to create your own button image (and rollover sprite) for the checkout button. But with a little extra CSS tweaking (like adding an background image to the miniCart div) my minicart now looks something like this and works just great!

ISE Custom Minicart

You can download my minicart CSS and my minicart Javascript, but please review it for compliance with your specific version of Interprise Suite. This was written for ISE 5.3.

For more information on customizing Interprise Suite eCommerce, please feel most welcome to contact the Hybrid Forge design team: info@hybridforge.com.