Checkout problems upgrading to Magento 1.9.3.4+

Magento version 1.9.3.4 include patch SUPEE-9767 V2 which includes security patching for the checkout process.

For your current front-end templates to work with this patch you will need to include a form key value to a number of forms in the checkout process.

<?php echo $this->getBlockHtml('formkey') ?>

Load the templates below from your  app/design/frontend/<package>/<theme> directory and add the Form Key code above between the <form> and </form> tags on each.

The basic templates that will need upgraded:

  • /template/checkout/cart/shipping.phtml
  • /template/checkout/onepage/billing.phtml
  • /template/checkout/onepage/shipping.phtml
  • /template/checkout/onepage/payment.phtml

If persistant checkout is enabled:

  • /template/checkout/onepage/shipping_method.phtml
  • /template/persistent/checkout/onepage/billing.phtml

If you allow shippinng to multiple addresses:

  • /template/checkout/multishipping/billing.phtml
  • /template/checkout/multishipping/shipping.phtml

Ordering assets in Magento 2

This one will come in useful until Magento 2 sorts itself out.

For some reason, Magento 2 has no way to order assets out of the box. There is now an extension which allows you to set an order attribute in the CSS tags of the layout XML files and layout updates in Admin Panel.

Github: Mage2 Ordered Assets by Quickshiftin

Example

Before

<head>
   <css src="css/app.css" />
</head>

After

<head>
   <css src="css/app.css" order="100" />
</head>

Magento Code: Check an import directory for new product CSVs and process using a Magmi profile

This script will first scan the var/import directory for all CSV files starting “import-” using the glob() function in PHP. It will return an array of any files which match the query in the directory including the file path from root.

The $file_parts will be used later when we need just the file name.

$cmd is the executable shell command we will be using to load Magmi, set the profile, mode and chosen file.

The shell_exec() function runs the command and will return any output to the $output variable, this can be expanded to check for a successful import. The script below will carry on regardless of import status.

Once the import is complete we take the CSV and copy it into an archive folder, just in case we want to reuse it. The original file is then deleted from the var/import folder using unlink()

This script can then either be run manually, or set-up as a scheduled task using Cron.

// Find all CSV files in import directory
$files = glob('/home/admin/public_html/var/import/import*.csv');

// For each of the files found 
foreach ($files as $file):

   // Explode for teh the file name in 6th position of the array
   $file_parts = explode("/",$file);

   // Set-up the command 
   $cmd = 'php /home/admin/public_html/magmi/cli/magmi.cli.php -profile=default -mode=create -CSV:filename="'.$file.'"';

   // Execute the comamnd 
   $output = shell_exec($cmd);

   // Copy the executed script into an archive folder
   if ( copy($file,'/home/admin/public_html/var/import/archive/'.$file_parts[6]) ):
      // Delete the original
      unlink($file);
   endif;

endforeach;

Magento Code: Include currency switcher in the header or footer with Foundation mark-up

It is easy to set-up multi-currencies in Magento. This code  allows you to quickly include a currency drop down or link to  the header or footer of your Magento store. Before you begin make sure you have enabled more than one currency  as this example won’t work without at least one additional currency alongside your base currency.

Set-up the following code in your theme directory /app/design/frontend/package/theme/template/currency/currency.phtml. I’ve included code for both a drop down select box, or inline list of hyperlinks.

Continue reading Magento Code: Include currency switcher in the header or footer with Foundation mark-up

Magento Code: Add a drop down attribute and display it on the product page in custom HTML

Magento makes it really easy to expand the usual product attributes through the Admin Panel. While these can be added to the product page in the standard attribute list table, you may want your attribute to appear differently or use it for another feature. This post explains how.

In this example we’ll be adding an attribute to tell the customer how long they might have to wait on a product to arrive.

Continue reading Magento Code: Add a drop down attribute and display it on the product page in custom HTML

Magento Issue: Unable to sort configurable product attribute drop down options

Having encountered this issue a couple of times I though it was time to make a note. This is a fix for an issue in Magento 1.9 whereby the order specified for option attributes in the admin panel are not being applied on the front end.

Jonathon Byrd at Merchant Protocol has published this fix which overrides the core Configurable Attribute Collection class with an updated one which properly sorts the attribute options by the sort value in the Admin panel.

» [Solved] Sort Configurable Product Attribute Options and Dropdowns

Jonathon’s fix works perfectly. I’ve implemented it alongside a simple product pricing module for configurable products also without issue.

MySQL TRUNCATE command: Quickly and easilty clear out the Magento database

This is a simple list of SQL commands which can be used to clear out various parts of the Magento database. It’ll be useful when creating a development environment from an existing database. It will clear all real customer, orders and sales data while keeping the catalogue and CMS information.

The basic command should be to disable foreign key checks in MySQL, followed by the required truncate commands, then reenable foreign key checks.

SET FOREIGN_KEY_CHECKS=0; 

Clear the log tables down

This should be managed by Magento but issues with Cron scheduling can mean they grow way beyond a reasonable size. Clearing the log tables will have no impact on the system.

TRUNCATE `log_customer`; 
TRUNCATE `log_quote`; 
TRUNCATE `log_summary`; 
TRUNCATE `log_summary_type`; 
TRUNCATE `log_url`; 
TRUNCATE `log_url_info`; 
TRUNCATE `log_visitor`; 
TRUNCATE `log_visitor_info`; 
TRUNCATE `log_visitor_online`; 

Clear out report tables

The report tables will, again, have no negative impact on your store but it will affect performance of some features including recently viewed products, and any reporting you do will need rebuilt before run again.

TRUNCATE `coupon_aggregated`;
TRUNCATE `coupon_aggregated_order`;
TRUNCATE `coupon_aggregated_updated`;
TRUNCATE `report_viewed_product_aggregated_daily`;
TRUNCATE `report_viewed_product_aggregated_monthly`;
TRUNCATE `report_viewed_product_aggregated_yearly`;
TRUNCATE `sales_bestsellers_aggregated_daily`;
TRUNCATE `sales_bestsellers_aggregated_monthly`;
TRUNCATE `sales_bestsellers_aggregated_yearly`;
TRUNCATE `sales_invoiced_aggregated`;
TRUNCATE `sales_invoiced_aggregated_order`;
TRUNCATE `sales_order_aggregated_created`;
TRUNCATE `sales_order_aggregated_updated`;
TRUNCATE `sales_refunded_aggregated`;
TRUNCATE `sales_refunded_aggregated_order`;
TRUNCATE `sales_shipping_aggregated`;
TRUNCATE `sales_shipping_aggregated_order`;
TRUNCATE `tax_order_aggregated_created`;
TRUNCATE `tax_order_aggregated_updated`;

Miscellaneous

TRUNCATE `catalogsearch_query`;
TRUNCATE `index_event`; 
TRUNCATE `index_process_event`;   
TRUNCATE `report_event`;
TRUNCATE `report_viewed_product_index`;
TRUNCATE `sendfriend_log`; 
TRUNCATE `tag`; 
TRUNCATE `tag_relation`; 
TRUNCATE `tag_summary`; 
TRUNCATE `wishlist`;

Remove customer information

-- Customerc
TRUNCATE `customer_entity`;
TRUNCATE `customer_entity_datetime`;
TRUNCATE `customer_entity_decimal`;
TRUNCATE `customer_entity_int`;
TRUNCATE `customer_entity_text`;
TRUNCATE `customer_entity_varchar`;

-- Customer Addresses
TRUNCATE `customer_address_entity`;
TRUNCATE `customer_address_entity_datetime`;
TRUNCATE `customer_address_entity_decimal`;
TRUNCATE `customer_address_entity_int`;
TRUNCATE `customer_address_entity_text`;
TRUNCATE `customer_address_entity_varchar`;

Sales Quotes and Order Data

-- Quotes
TRUNCATE `sales_flat_quote`; 
TRUNCATE `sales_flat_quote_address`; 
TRUNCATE `sales_flat_quote_address_item`; 
TRUNCATE `sales_flat_quote_item`; 
TRUNCATE `sales_flat_quote_item_option`; 
TRUNCATE `sales_flat_quote_payment`; 
TRUNCATE `sales_flat_quote_shipping_rate`; 

-- Orders
TRUNCATE `sales_flat_order`; 
TRUNCATE `sales_flat_order_address`; 
TRUNCATE `sales_flat_order_grid`; 
TRUNCATE `sales_flat_order_item`; 
TRUNCATE `sales_flat_order_payment`; 
TRUNCATE `sales_flat_order_status_history`;

-- Invoices
TRUNCATE `sales_flat_invoice`;
TRUNCATE `sales_flat_invoice_comment`;
TRUNCATE `sales_flat_invoice_grid`;
TRUNCATE `sales_flat_invoice_item`;

-- Shipments
TRUNCATE `sales_flat_shipment`;
TRUNCATE `sales_flat_shipment_comment`;
TRUNCATE `sales_flat_shipment_grid`;
TRUNCATE `sales_flat_shipment_item`;
TRUNCATE `sales_flat_shipment_track`;

-- Sales Order Tax
TRUNCATE `sales_order_tax`;
TRUNCATE `sales_order_tax_item`;

-- Creditmemos
TRUNCATE `sales_flat_creditmemo`;
TRUNCATE `sales_flat_creditmemo_comment`;
TRUNCATE `sales_flat_creditmemo_grid`;
TRUNCATE `sales_flat_creditmemo_item`;

After each update, re-enable foreign key checks.

SET FOREIGN_KEY_CHECKS=1;

All-in-one Google Analytics tracking in Magento

Simple single script to add Google’s conversion tracking to your Magento ecommerce website. The code should be added into the footer.phtml file within your current template. The code includes tracking of catalogue browsing, checkout and new orders.

Simply replace all the $googleConversionId with your actual Google Conversion ID.

<!-- Google Conversion Tracking -->
<?php $googleConversionId = ""; // Your conversion ID goes here ?>
<?php $page_type = Mage::app()->getFrontController()->getRequest()->getControllerName();
if($page_type == 'index') { ?>
 <script type="text/javascript">
 var google_tag_params = {
 ecomm_pagetype: 'home',
 ecomm_prodid: '',
 ecomm_totalvalue: 0
 };
 </script>
<?php } elseif($page_type == 'category') { ?>
 <script type="text/javascript">
 var google_tag_params = {
 ecomm_pagetype: 'category',
 ecomm_prodid: '',
 ecomm_totalvalue: 0
 };
 </script>
<?php } elseif($page_type == 'product') {
 $product_id = Mage::registry('current_product')->getId();
 $product_id = Mage::getModel('catalog/product')->load($product_id)->getSku();
 $product_price = Mage::registry('current_product')->getPrice();
 ?>
 <script type="text/javascript">
 var google_tag_params = {
 ecomm_pagetype: 'product',
 ecomm_prodid: '<?php echo $product_id; ?>',
 ecomm_totalvalue: parseFloat('<?php echo $product_price; ?>')
 };
 </script>
<?php } elseif($page_type == 'cart') { ?>
 <script>
 var id = new Array();
 var price = new Array();
 </script>
 <?php
 $cart = Mage::getModel('checkout/session')->getQuote();
 foreach ($cart->getAllItems() as $item) {
 $product_id = $item->getProductId();
 $product_id = $item->getSku();
 $product_id_all = $product_id_all.','.$product_id ;
 $productPrice = $item->getProduct()->getPrice();
 $productPrice_all = $productPrice_all.','.$productPrice;
 ?>
 <Script>
 id.push('<?php echo $product_id; ?>');
 price.push(parseFloat('<?php echo $productPrice; ?>'));
 </Script>
 <?php
 }
 $product_id_all=substr($product_id_all, 1);
 $productPrice_all=substr($productPrice_all, 1);
 ?>
 <script type="text/javascript">
 var google_tag_params = {
 ecomm_pagetype: 'cart',
 ecomm_prodid: id,
 ecomm_totalvalue: price
 };
 </script>
 <?php } elseif($page_type == 'onepage') { ?>
 <script>
 var id = new Array();
 var price = new Array();
 </script>
 <?php
 $cart = Mage::getModel('checkout/session')->getQuote();
 foreach ($cart->getAllItems() as $item)
 {
 $product_id = $item->getProductId();
 $product_id = $item->getSku();
 $product_id_all = $product_id_all.','.$product_id ;
 $productPrice = $item->getProduct()->getPrice();
 $productPrice_all = $productPrice_all.','.$productPrice;
 ?>
 <Script>
 id.push('<?php echo $product_id; ?>');
 price.push(parseFloat('<?php echo $productPrice; ?>'));
 </Script>
 <?php } 
 $product_id_all=substr($product_id_all, 1);
 $productPrice_all=substr($productPrice_all, 1);
 ?>
 <script type="text/javascript">
 var google_tag_params = {
 ecomm_pagetype: 'purchase',
 ecomm_prodid: id,
 ecomm_totalvalue: price
 };
 </script>
 <?php }else{ ?>
 <script type="text/javascript">
 var google_tag_params = {
 ecomm_pagetype: 'other',
 ecomm_prodid: '',
 ecomm_totalvalue: 0
 };
 </script>
 <?php } ?>
<script type="text/javascript">
 /* <![CDATA[ */
 var google_conversion_id = <?php echo $googleConversionId; ?>;
 var google_custom_params = window.google_tag_params;
 var google_remarketing_only = true;
 /* ]]> */
</script>
<script type="text/javascript" src="//www.googleadservices.com/pagead/conversion.js">
</script>
<noscript>
 <div style="display:inline;">
 <img height="1" width="1" style="border-style:none;" alt="" src="//googleads.g.doubleclick.net/pagead/viewthroughconversion/<?php echo $googleConversionId; ?>/?value=0&amp;guid=ON&amp;script=0"/>
 </div>
</noscript>
<!-- End Google Conversion Tracking -->

All-in-one Facebook Pixel Code for Magento ecommerce

Simple single script to add Facebook’s Pixel Code tracking to your Magento ecommerce website. The code should be added into the head.phtml file within your template. This includes tracking of search and checkout progress and new orders.

Simply replace all the $facebookPixelId with your actual Facebook Pixel Code ID.

<!-- All in one Facebook Pixel Code --> 
<?php $facebookPixelId = "000000000000000000000"; // Your Pixel Code goes here ?>
<script> 
 !function(f,b,e,v,n,t,s){if(f.fbq)return;n=f.fbq=function(){n.callMethod? 
 n.callMethod.apply(n,arguments):n.queue.push(arguments)};if(!f._fbq)f._fbq=n; 
 n.push=n;n.loaded=!0;n.version='2.0';n.queue=[];t=b.createElement(e);t.async=!0; 
 t.src=v;s=b.getElementsByTagName(e)[0];s.parentNode.insertBefore(t,s)}(window, 
 document,'script','//connect.facebook.net/en_US/fbevents.js');
 fbq('init', '<?php echo $facebookPixelId; ?>'); 
 fbq('track', "PageView");
<?php 
 $request = $this->getRequest();
 $module = $request->getModuleName();
 $controller = $request->getControllerName();
 $action = $request->getActionName();
 $pageIdentifier = Mage::app()->getFrontController()->getAction()->getFullActionName(); 
 // Lead
 if(Mage::registry('current_product')) {
 echo "fbq('track', 'Lead');";
 }
 // Search
 if($controller == 'result' || $controller =='advanced') { 
 echo "fbq('track', 'Search');"; 
 }
 // Customer registration
 if($module == 'customer' && $controller == 'account' && $action == 'index'){
 echo "fbq('track', 'CompleteRegistration')";
 }
 // Add to cart
 if($module == 'checkout' && $controller == 'cart' && $action == 'index') {
 echo "fbq('track', 'AddToCart');";
 }
 // Add to wishlist
 if($module == 'wishlist') {
 echo "fbq('track', 'AddToWishlist');";
 }
 // Checkout start 
 if(Mage::getURL('checkout/onepage') == Mage::helper('core/url')->getCurrentUrl()) {
 echo "fbq('track', 'InitiateCheckout');";
 
 // As the onepagecheckout don't have a specific page for add billing info, i placed the tracker here
 echo "fbq('track', 'AddPaymentInfo');";
 }
 // Checkout success
 if ($pageIdentifier == 'transparente_standard_redirect') {
 $lastOrderId = Mage::getSingleton('checkout/session')->getLastOrderId();//Geeting last order id
 $order = Mage::getSingleton('sales/order'); //getting order model
 $order->load($lastOrderId); //loding current order
 $_totalData =$order->getData(); //loading order model data
 $grandTotal = number_format($_totalData['grand_total'],2,'.',''); //loading grand total
 echo "fbq('track', 'Purchase', {value: '$grandTotal', currency: 'BRL'});";
 }
 ?>
</script> 
<noscript><img height="1" width="1" style="display:none" 
src=" https://www.facebook.com/tr?id=<?php echo $facebookPixelId; ?>&ev=PageView&noscript=1" 
/></noscript> 
<!-- All in one End Facebook Pixel Code -->

Add Facebook Pixel Code to Magento Success Page

Update: Instead of this, try the All-in-one Facebook Pixel Code method. It’s easier to maintain.

Facebook Pixel Code is a new and even more complicated way to annoy web developers, so on top of all the Google Analytics we now have even more random JavaScript to drop into pages already growing under the weight of like and share buttons, analytics tracking, advert tracking on top of the code that actually makes the website work. Good times.

Anyhoo, this is the process for adding a successful order tracking. It all takes place on the success.phtml page or your theme so go ahead and open the file: app\design\frontend\PACKAGE\THEME\template\checkout\success.phtml

Facebook conversion tracking requires the order total. Add the following PHP to set the last order to an amount variable which can be reused later in the tracking code.

<?php
//Get Order Number & Order Total
$order = Mage::getModel('sales/order')->loadByIncrementId(Mage::getSingleton('checkout/session')->getLastRealOrderId());
$amount = number_format($order->getGrandTotal(),2);
?>

Finally, add the Facebook conversion code itself. Be sure to substitute the 100000001 below with the value form your Facebook conversion code – it appears twice in the JavaScript and the Image SRC. Also you may need to modify the currency parameter, again it appears twice.

<script type="text/javascript">
var fb_param = {};
fb_param.pixel_id = '100000001';
fb_param.value = '<?php echo $amount; ?>';
fb_param.currency = 'GBP';
(function(){
  var fpw = document.createElement('script');
  fpw.async = true;
  fpw.src = '//connect.facebook.net/en_US/fp.js';
  var ref = document.getElementsByTagName('script')[0];
  ref.parentNode.insertBefore(fpw, ref);
})();
</script>
<noscript><img height="1" width="1" alt="" style="display:none" src="https://www.facebook.com/offsite_event.php?id=100000001&amp;value=<?php echo $amount; ?>&amp;currency=GBP" /></noscript>

You can now go ahead and test to confirm.

Quickfix: Quickly add a new Magento CMS page template

Sometimes it’s necessary to quickly add a template for a page into the Magento content management system. This can be done via a custom extension below is the quick fix if required.

Find the closing global tag </global> and add the following code above it. It will add two templates one from homepage.phtml and one for another-page.html which can then be set on the Design Tab in CMS > Pages.

<global>
    <cms>
        <layouts>
            <homepage>
                <label>Homepage</label>
                <template>page/homepage.phtml</template>
            </homepage>
            <another_page>
                <label>Abother Page</label>
                <template>page/another-page.phtml</template>
            </another_page>
        </layouts>
    </cms>
</global>