branko ajzele, senior developer / project manager

Posts / Articles

WordPress and Magento integration – One way to go

Lot of us in Magento related development have an issue of connecting their Magento with other CMS solutions out there. Lot of our clients like and want WordPress alongside Magento. WordPress is a great platform when it comes to publishing and managing articles. Not to mention the SEO stuff. One of the biggest issue with integrating two systems in PHP is the lack of the namespaces. This leads to function name redeclaration issues and so on. Integrating something into something is such a loosely term, depending on level of integrations… If you ask me :)

In this article, I’ll give you one way of how you can integrate your WordPress (or any other CMS) with Magento. If you read the article written at http://www.magentocommerce.com/blog/comments/tutorial-integrating-3rd-party-cms-content-within-magento, then you will on clear with my article. The approach is somewhat similar. There is one issue I see with the integration in the link I provided. You see, integration is done in such way that you fool no_route controller in Magento to ignore 404 template for no route and send a request to some other url then load that url content into the block that was previously used by 404 template.

Now, either I’m missing something or… The biggest issue I see with the above approach are the URL links of the content returned to us. Let’s suppose our shop is located on http://example-shop.domain/ and our WordPress at http://example-shop.domain/articles/. When we implement solution above we get some stuff under http://example-shop.domain/my-wordpress-article-no1, which is generally found under http://example-shop.domain/articles/my-wordpress-article-no1.

Now, if we had some auto generated links inside that post, my-wordpress-article-no1, pointing to other articles in my WordPress then those links would have url’s like http://example-shop.domain/articles/my-wordpress-article-no2, http://example-shop.domain/articles/my-wordpress-article-no3 and so on. Notice the /articles part in them? Clicking on such links would drove us away from Magento part of the site. We could theoretically access those articles by simply using direct link to http://example-shop.domain/my-wordpress-article-no2 since above method would interpret that as /auto and fetch it for us. How do we deal with this? Have no idea… Url rewrite? What about all of those WordPress plugins out there… Do we know what effect would above method have on that kind of integration. I don’t. That’s why I wrote another kind of integration.

Important: This is merely MY WAY of resolving this issue, and as such is more of a temporary approach. Since I’m not quite satisfied with this one as well :)

First let me define what I mean by integration of WordPress and Magento:

  • They are both installed each in it’s own directory
  • WordPress uses Magento’s .css files
  • WordPress uses (includes, trough class I wrote below) Magento’s header and footer
  • WordPress utilities jQuery for a little help in patching up some holes by use of COOKIES

Final result:
All of the header and footer stuff in WordPress is used from Magento so you do not need to restyle it in WordPress. All you need to do is to style and work on the content area of the WordPress template output.

Steps:
1) Do the full styling of Magento part. After that, 1column.phtml file and surround the header output stuff with comments like:

<!-- STARTHeaderContainer --><div class="header-container"><?php echo $this->getChildHtml('header') ?></div><!-- ENDHeaderContainer -->

2) Do the same for footer output stuff in same file:

<!-- STARTFooterContainer --><div class="footer"><?php echo $this->getChildHtml('footer') ?></div><!-- ENDFooterContainer -->

3) Go to Magento Admin > CMS > Manage pages > Add new… call it “empty” or whatever, set it active, assign this page to use 1column layout. You should now be able to access this page using url like http://example-shop.domain/empty. It should show minimal page with only header and footer stuff. If you see some additional block then go back to edit page and under layout updates place
4) Go to WordPress theme folder, open functions.php file, copy paste the class ActiveCodeline_ConnectWM into it.
5) Inside WordPress theme folder, open header.phtml and instantiate a class like:

<?php
$parts = new ActiveCodeline_ConnectWM('http://example-shop.domain/empty');
echo $parts->renderHeader();
?>

And here is the class content:

class ActiveCodeline_ConnectWM
{
private $_content;
private $_header;
private $_footer;
 
/**
* Assign a url to some lightweight Magento page, posible 1 column, empty CMS page
*/
public function __construct($url, $markerStartHeader = null, $markerEndHeader = null, $markerStartFooter = null, $markerEndFooter = null)
{
$this->_content = file_get_contents($url);
$this->_renderHeader($markerStartHeader, $markerEndHeader);
$this->_renderFooter($markerStartFooter, $markerEndFooter);
}
 
public function renderHeader($markerStart = null, $markerEnd = null)
{
return $this->_header;
}
 
private function _renderHeader($markerStart = null, $markerEnd = null)
{
$markerStart = (is_null($markerStart)) ? '<!-- STARTHeaderContainer -->' : (string)$markerStart;
$markerEnd = (is_null($markerEnd)) ? '<!-- ENDHeaderContainer -->' : (string)$markerEnd;
 
$headerStart = stripos($this->_content, $markerStart);
$headerEnd = stripos($this->_content, $markerEnd);
 
$this->_header = substr($this->_content, $headerStart, $headerEnd-$headerStart);
}
 
public function renderFooter()
{
return $this->_footer;
}
 
private function _renderFooter($markerStart = null, $markerEnd = null)
{
$markerStart = (is_null($markerStart)) ? '<!-- STARTFooterContainer -->' : (string)$markerStart;
$markerEnd = (is_null($markerEnd)) ? '<!-- ENDFooterContainer -->' : (string)$markerEnd;
 
$footerStart = stripos($this->_content, $markerStart);
$footerEnd = stripos($this->_content, $markerEnd);
 
$this->_footer = substr($this->_content, $footerStart, $footerEnd-$footerStart);
}
 
}

Upon refresh of WordPress home page you should now see the Mageno header loaded. Now, for the sweet part, transfering customer related info, like cart item status and so on.

Inside WordPress header file you can use stuff like:

...
<?php wp_head(); ?>

<script type="text/javascript">
jQuery(document).ready(function() {
jQuery("#totalItemsCount").html("<?php echo $_COOKIE['my_cart_items'] ?>");
jQuery("#totalItemsPrice").html("<?php echo $_COOKIE['my_cart_total'] ?>");
});
...
</script>

Notice the $_COOKIE['my_cart_items'] ?>. Let’s say we wish to see total number of items in cart and total price of added items. Nice little feature inside our header that lots of clients look for. Here is how, open your header.phtml from Magento folder, and copy paste the code:

$totalNumOfCartItem = Mage::helper('checkout/cart')->getCart()->getItemsCount();
 
$totalPrices = Mage::helper('checkout/cart')->getCart()->getQuote()->getTotals();
 
$subtotalPrice = $totalPrices['subtotal'];
$subtotalPrice = $subtotalPrice->getData('value');
 
$grandTotal = $totalPrices['grand_total'];
$grandTotal = $grandTotal->getData('value');
 
setcookie('my_cart_items', $totalNumOfCartItem);
setcookie('my_cart_total', Mage::helper('core')->currency($grandTotal, true, false));

Combined with something like (inside header.phtml)

 
<div id="mini_mycart">
<ul>
<li id="tnpart_mycart">
<p>items: <span id="totalItemsCount"><?php if(isset ($totalNumOfCartItem)) { echo $totalNumOfCartItem; } else { echo '0'; } ?></span><br />
total: <span id="totalItemsPrice"><?php if(isset($grandTotal)) { echo Mage::helper('core')->currency($grandTotal, true, false); } else { echo Mage::helper('core')->currency('0', true, false); } ?></span></p>
</li>
<li id="tnpart_view_mycart"><a href="<?php echo $this->getUrl().'checkout/cart/'; ?>" title="View my cart"><span class="b1">View my cart</span></a></li>
<li id="tnpart_wishlist"><a href="<?php echo $this->getUrl().'wishlist/'; ?>" title="My wishlist"><span class="b1">My wishlist</span></a></li>
<li id="tnpart_checkout"><a href="<?php echo $this->getUrl().'checkout/onepage/'; ?>" title="Checkout"><span class="b1">Checkout</span></a></li>
</ul>
 
<p id="submini_account_action">
<a href="#" title="My account">my account</a>
<span class="delimiter1">|</span>
<a href="#" title="Login">login</a>
</p>
</div><!-- /mini_mycart -->

And you get cart info on both Magento and WordPress side (hence the jQuery stuff). This walk-trough is not for newbies. I did not go in such details so some stuff might be unclear. However, all of the code you need to make it work is here.

View Comments

  1. Thanks for sharing – that was easy to implement and the result is a much better integration than the exiting one… :)

  2. I got well till last point – when I add your code to see the number of products – I get this error: PHP Fatal error: Cannot redeclare __() in /home/xxx/app/code/core/Mage/Core/functions.php on line 104

    This is what I have in my header.phtml

    <a href=”getUrl(”) ?>”><img src=”getLogoSrc() ?>” alt=”getLogoAlt() ?>”/>
    <img src=”getSkinUrl(‘images/side_logo_promo.gif’) ?>” alt=”" class=”side-logo-promo”/>

    getChildHtml(‘topSearch’) ?>
    getChildHtml(‘cart’) ?>

    getChildHtml(‘topLinks’) ?>
    getChildHtml(‘store_language’) ?>

    getChildHtml(‘topMenu’) ?>

    and this is what i’m adding before that code:
    $totalNumOfCartItem = Mage::helper(‘checkout/cart’)->getCart()->getItemsCount();

    $totalPrices = Mage::helper(‘checkout/cart’)->getCart()->getQuote()->getTotals();

    $subtotalPrice = $totalPrices['subtotal'];
    $subtotalPrice = $subtotalPrice->getData(‘value’);

    $grandTotal = $totalPrices['grand_total'];
    $grandTotal = $grandTotal->getData(‘value’);

    setcookie(‘my_cart_items’, $totalNumOfCartItem);
    setcookie(‘my_cart_total’, Mage::helper(‘core’)->currency($grandTotal, true, false));

    But setcookie is actually triggering the errors…any ideas or workarounds?

  3. @Pete

    Are you doing some kind of include? Your error should not be related to this article’s walk trough steps. Since, at no point have I done include of any of the Magento files into the WordPress. I only retrieved html content from one of the Magento page url’s.

    This error often happens when you try directly including Magento files into WordPress or other way round.

  4. James /

    Hi Branko, Thanks for sharing the code.

    I tried implementing it but is getting this error:

    Parse error: syntax error, unexpected T_STRING, expecting T_OLD_FUNCTION or T_FUNCTION or T_VAR or ‘}’ in /home/myserver-name/public_html/wordpress/wp-content/themes/lsdnew/functions.php on line 5

    line #5 in function.php is this: “private $_content;”.

    Also, it’s a bit unclear to me on #4 and #5 in your instruction:

    In #4
    4) Go to WordPress theme folder, open functions.php file, copy paste the class ActiveCodeline_ConnectWM into it.

    I gather the “class ActiveCodeline_ConnectWM” is the second php code correct?

    5) Inside WordPress theme folder, open header.phtml and instantiate a class like:

    and #5 is for this correct (note: you wrote “header.phtml” so for a while I thought it’s for magento’s header.phtml)?
    “renderHeader();
    ?>”

    Anyway, I tried both method by paste #5 code into functions.php and #4 code into header.php, and I am getting similar error that is complaining
    “private $_content;” with different error message

    Will the server configuration cause the error? I tried implemented the wordpress-magento integration from the tutorial that Varien provided, and was having issue that was caused by server configuration.

    p/s. I have no include function in my wordpress theme.

  5. Thanks for this article, it helped a lot on one of the projects I just completed. In addition to bringing some Magento content into WP, I used this technique to bring some WP content into Magento!

    I had read numerous places about how you can execute Magento code externally (Mage::app();) and access the MAgneto cookie… but in my case Magento was one directory above (/store) the WP install and I could never get it work, so this little hack did the trick instead.

    One note: I couldn’t use “file_get_contents” because of my server configuration, but I was able to cURL instead.

    You make a good point about the Link problem with the “Noroute” integration method on the Magento wiki, but I noticed two other problems which kept me from using this method:

    1. The page HTTP response headers are all 404/Not Founds! Bad form to serve the right content and the wrong header.
    2. There is no clean way to get page titles and meta (keywords, description, and canonical urls) from the wordpress pages. If you override _prepareLayout() as well as _toHtml() you can set them, but it’s kind of ugly and difficult to pass some of that information from WordPress.

    Better to bring Magento content into WP with your technique right now, I think.

    Cheers!

  6. @thaddeusmt Nice to hear it helped :) Cheers.

  7. Thanks so much for this tutorial. Very good code. However, I’m having a problem with the 1column.phtml file. When I add the etc., it throws off the formatting (for all pages using the 1 column layout). When I remove them, the problem goes away. Any idea why this could be happening? I’m out of ideas!

    Thanks so much!
    Matt

  8. I forgot to mention. It is only problematic in IE.

  9. mohan /

    Hi Branko,
    can we extend this technique to drupal or joomla?

  10. @mohan I see no reason why not. This technique is not tied to WordPress by no means. You can take simple .php file without any CMS system, include the class, and to the same.

    The point is simple, just fetch the header and footer area of some site (in this case Magento site).

  11. Hi Branko,

    I have successfully implemented your Mage – WP integration and it works fine. However, I have the My Cart link in the header and, in the shop part, when you add products it displays the number of items in the cart. However, when I go to the articles section which loads wordpress in the middle, I also lose the cart items display in the header. My guess is that this must be due to the loss of cookies when the Magento empty page is retrieved from the WP side.

    Is there any way to preserve the cart items display when browsing the articles part?

    Thanks.

  12. Hey, it’s been a while since my previous question. I just revisited the issue of the cart items display getting lost wen switching from the Magento site to the WordPress site.

    The issue with the method in the article above is that it doesn’t create a stream context when it gets the magento page. So, to preserve our header with the welcome message and cart items display, we need to create a stream context and add the ‘frontend’ cookie that magento sets.

    The code now becomes:


    $opts = array('http' => array('method' => 'GET', 'header' => "Accept-language: en\r\nCookie: frontend=".$_COOKIE['frontend']."\r\n"));
    $context = stream_context_create($opts);
    $this->_content = file_get_contents($url, FILE_TEXT, $context);

    And, voila, everything is fine again.

    Hope this helps someone.

  13. @Robert Thnx for the feedback. My apologies for not getting back to you or anyone else, I am truly busy for most of the time.

  14. Thanks Branko for the script… After a couple of hours I finally got the script working.. The only problem I still have is the one Robert had.. Is it possible to explain what he did or were I should put the code Robert added as Comment?

    Thanks,

  15. @Branko, no worries, busy is good :) I understand. I’m like that too most of the time.

    @Miquil, I have admittedly altered the Connect_WM class a little and here’s the full code from [wp_root]/wp-content/themes/your_theme/functions.php


    class ActiveCodeline_ConnectWM
    {
    private $_content;
    private $_header;
    private $_footer;

    /**
    * Assign a url to some lightweight Magento page, posible 1 column, empty CMS page
    */
    public function __construct($url, $markerStartHeader = null, $markerEndHeader = null, $markerStartFooter = null, $markerEndFooter = null)
    {
    $opts = array('http' => array('method' => 'GET', 'header' => "Accept-language: en\r\nCookie: frontend=".$_COOKIE['frontend']."\r\n"));
    $context = stream_context_create($opts);
    $this->_content = file_get_contents($url, FILE_TEXT, $context);
    $this->_renderHeader($markerStartHeader, $markerEndHeader);
    $this->_renderFooter($markerStartFooter, $markerEndFooter);
    }

    public function renderHeader($markerStart = null, $markerEnd = null)
    {
    return $this->_header;
    }

    private function _renderHeader($markerStart = null, $markerEnd = null)
    {
    $markerStart = (is_null($markerStart)) ? '' : (string)$markerStart;
    $markerEnd = (is_null($markerEnd)) ? '' : (string)$markerEnd;

    $headerStart = stripos($this->_content, $markerStart);
    $headerEnd = stripos($this->_content, $markerEnd);

    $this->_header = substr($this->_content, $headerStart, $headerEnd-$headerStart);
    }

    public function renderFooter()
    {
    return $this->_footer;
    }

    private function _renderFooter($markerStart = null, $markerEnd = null)
    {
    $markerStart = (is_null($markerStart)) ? '' : (string)$markerStart;
    $markerEnd = (is_null($markerEnd)) ? '' : (string)$markerEnd;

    $footerStart = stripos($this->_content, $markerStart);
    $footerEnd = stripos($this->_content, $markerEnd);

    $this->_footer = substr($this->_content, $footerStart, $footerEnd-$footerStart);
    }
    }
    $parts = new ActiveCodeline_ConnectWM('http://'.$_SERVER['SERVER_NAME'].'/empty');

  16. Oh, and later, when you want to show the header/footer just call:


    global $parts;
    echo $parts->renderHeader();
    ...
    echo $parts->renderFooter()

  17. Thanks alot, i was just thinking how i was going to implement a blog feature into magento – which i only just came across after trying to implement a cart feature into ning platform – to no avail i looked at wordpress and learnt of magento and the big brands that use it blew me away.

    Ok, now if anyone could clear up something for me.

    Magento – do i simply register and then it will alow me to add my free theme that i have into it.

    ?

  18. fernandoolea /

    Hello everybody,

    I tried this with magento 1.3.2.1 and WordPress 2.8.5 without success, i think is because the css, how do i configure wordpress to use magento css? because my header appear without any images..

    Sorry for dummy question and my bad English

    Thanks a lot

  19. This does not do anything for synchronizing accounts or user logins, correct?

    I am looking for a WordPress to Magento integration that will synchronize user account data, and log users into both apps at once. That way a logged in user can comment on blog posts without having to register and maintain two accounts on my site.

  20. Hi,

    For step #5, there does not exist header.phtml in the WordPress theme folder. I tried completing that step in Magento's header.phtml but obviously that did not work either.

    What am I doing wrong?

  21. Hi,

    Great code guys thanks for sharing! If you are using Robert's excellent cookie code addon to get the cart items etc in wordpress, then consider using:

    if(isset($_COOKIE['frontend'])) {
    $opts = array('http' => array('method' =>
    'GET', 'header' => “Accept-language: enrnCookie:
    frontend=”.$_COOKIE['frontend'].”rn”));
    } else {
    $opts = array('http' => array('method' =>
    'GET', 'header' => “Accept-language: enrn”));
    }

    to avoid Magento choking if people visit the blog before ever visiting the store (on session_start in app/code/core/Mage/Core/Model/Session/Abstract/Varien.php).

  22. finch8243 /

    Great modification, we're using on our blog. One question — how do you get it to work when you enable permalinks in WordPress? The htaccess file screws up the class's call on this line:

    ActiveCodeline_ConnectWM('http://example-shop.domain/empty');

    Ideas?

  23. We're making use of Magento ver. 1.3.2.3 and we're trying to get the amount of items in the cart making use of the cookie code mentioned here, but unfortunately we're getting a fatal error: Uncaught exception 'Mage_Core_Model_Session_Exception'

    Is there something we're overlooking? Thanks in advance for your help!

  24. We're making use of Magento ver. 1.3.2.3 and we're trying to get the amount of items in the cart making use of the cookie code mentioned here, but unfortunately we're getting a fatal error: Uncaught exception 'Mage_Core_Model_Session_Exception'

    Is there something we're overlooking? Thanks in advance for your help!

  25. I second the permalink issue, that would be great if we could have SEO permalinks instead of the default ones. Is there any way to do this?

  26. I second the permalink issue, that would be great if we could have SEO permalinks instead of the default ones. Is there any way to do this?

  27. Thank you for posting step by step information on how to integrate magento in wordpress..

  28. anxiety /

    great guide. It helps especialy when WP doesnt come up to help as quick as possible

  29. We've made a minor up extension to supplement a Magento/Wordpress integration.

    We've made it available here: http://www.sonassi.com/knowledge-base/magento-k...

  30. spenserbaldwin /

    You're nuts that you've figured this stuff out. Does it follow logically that one can do this for almost any part of Magento into WordPress?

  31. spenserbaldwin /

    Just call for the correct stylesheet in the header.php w/i your wordpress directory.

  32. narayan123 /

    Hi Branko, I have integrated magento and wordpress together according to your previous said procedure(http://www.magentocommerce.com/blog/comments/tutorial-integrating-3rd-party-cms-content-within-magento). I have installed wordpress in a folder named 'wp' in magento root folder and written the same code in my httaccess file which is placed in wordpress root. I have used 3colums layout. I followed the same procedure, now i am geting my content in magento cms page from wordpress. But this is working very fine in my localhost(my local machine) but when i am trying this procedure in my server, it throws me an error like 'Access forbidden!

    You don't have permission to access the requested object. It is either read-protected or not readable by the server.

    If you think this is a server error, please contact the webmaster.
    Error 403', My webserver url is 'http://navsoft.co.in:8088/Eltronicnew/privacy-policy' , I have given 0777 permission to my all project subfolder. Please help me, how i will resolve this issue. I have wasted around 3 days to solve, but no result. Any help is highly appreciated. Thanks in advance.

  33. Revenhead /

    Thanks for the post, I'm looking for an experienced Magento developer for an in-house project that kicks off in two weeks. Would you have any recommendations?

    We are a small design and development shop near Charlotte, NC. Specialize in Drupal and WordPress development but we have had several Magento proposals lately and one is signed and ready to go.

    Top rate is $35 per hour depending on experience. I've read about your company today looking through Magento information and trying to find a credible way to find a Magento developer.

    Thanks,

    Chad

  34. richardferaro /

    Hi, I tried to run a different way of integrating Magento’s session within WordPress thru Mage.php.

    http://mysillypointofview.wordpress.com/2010/04...

  35. First off, thank you for so many great articles Branko, I especially enjoyed the article on the getData and getData methods.

    Okay, I wanted to ask if this has been used with Magento 1.4? I just tried implementing this with Magento 1.4.0.1 and WP 2.9.2 and was uncessful at the point where WP should have pulled in the header from Magento.

    Kind Regards,
    Bret

Trackbacks/Pingbacks

  1. Use Magento Template 4 Wp Wrap : Designers community - [...] http://activecodeline.com/wordpress-and-magento-integration-one-way-to-go/ [...]
  2. Erfarenheter av Lazzymonks Wordpress extension till Magento - Swedmedia Utveckling | Internet, trender & analyser - [...] http://activecodeline.com/wordpress-and-magento-integration-one-way-to-go/ [...]
blog comments powered by Disqus