How to add an external javascript/css file to Magento?

Featured Image

image by mauricesvay left @flickr

Have you ever had a need for adding external files into your Magento layout?
If you had then you know that you cannot do that from your xml layout files using methods/action:

<action method="addJs">
<action method="addCss">
or
<action method="addItem">

You could do that by hard-coding your “head.phtml” file, but then those external files will be loaded on all Magento pages.
This simple extension will provide you easy access for adding/removing external files such as JavaScript or CSS, libraries from remote servers which you cannot or don’t want to put on your server.
I called it Inchoo_Xternal extension.

How wonderful it would be if you could add or remove external, let’s say JavaScript libraries:
prototype: https://ajax.googleapis.com/ajax/libs/prototype/1.7.0.0/prototype.js
or
jquery: https://ajax.googleapis.com/ajax/libs/jquery/1.5.0/jquery.js
from yours “layout.xml” file and without modifying/hard-coding yours “head.phtml”.

Extension is very simple and it exists from only one Block class which extends and rewrites “Mage_Page_Block_Html_Head” class and configuration files of modules.
config.xml:

<?xml version="1.0"?>
<config>
    <modules>
        <Inchoo_Xternal>
            <version>1.0.0</version>
        </Inchoo_Xternal>
    </modules>
    <global>
        <blocks>
            <inchoo_externals>
                <class>Inchoo_Xternal_Block</class>
            </inchoo_externals>
            <page>
                <rewrite>
                    <html_head>Inchoo_Xternal_Block_Html_Head</html_head>
                </rewrite>
            </page>
        </blocks>
    </global>
    <frontend>
        <layout>
            <updates>
                <inchoo_xternal module="Inchoo_Xternal">
                    <file>inchoo_xternal.xml</file>
                </inchoo_xternal>
            </updates>
        </layout>
    </frontend>
</config>

Block class is very simple and it have 2 new methods I have called:
removeExternalItem which do the same as removeItem
and
addExternalItem also do the same as addItem
but I have added new types:
external_css
external_js

which loads external libraries.
Here is example of my layout.xml:

<layout version="0.1.0">
	<default>
            <reference name="head">
                <action method="addItem"><type>external_css</type><name>http://developer.yahoo.com/yui/build/reset/reset.css</name><params/></action>
                <action method="addItem"><type>external_js</type><name>http://yui.yahooapis.com/2.8.2r1/build/yahoo-dom-event/yahoo-dom-event.js</name><params/></action>
                <action method="addExternalItem"><type>external_js</type><name>http://yui.yahooapis.com/2.8.2r1/build/imageloader/imageloader-min.js</name><params/></action>
                <action method="addExternalItem"><type>external_css</type><name>http://yui.yahooapis.com/2.8.2r1/build/fonts/fonts-min.css</name><params/></action>
            </reference>
	</default>
	<catalog_product_view>
		<reference name="head">
                <action method="removeItem"><type>external_css</type><name>http://developer.yahoo.com/yui/build/reset/reset.css</name><params/></action>
                <action method="removeItem"><type>external_js</type><name>http://yui.yahooapis.com/2.8.2r1/build/yahoo-dom-event/yahoo-dom-event.js</name><params/></action>
                <action method="removeExternalItem"><type>external_js</type><name>http://yui.yahooapis.com/2.8.2r1/build/imageloader/imageloader-min.js</name><params/></action>
                <action method="removeExternalItem"><type>external_css</type><name>http://yui.yahooapis.com/2.8.2r1/build/fonts/fonts-min.css</name><params/></action>
            </reference>
	</catalog_product_view>
</layout>

As you can see from this example, external libraries are loaded on all the pages but product view page.

Download Inchoo_Xternal extension for easily adding external javascript and css files.

Enjoy coding!

50
Top

Care to rate this post?

Author

Vedran Subotic

Ex. Inchooer

Vedran worked in Inchoo from 2009 to 2012 as a backend developer.

Other posts from this author

Discussion 50 Comments

Add Comment
  1. How much different would be using such xml code to include external JS file:

    <block type="core/text" name="google.jquery">
    	<action method="setText">
    		<text><![CDATA[<script type="text/javascript" src="http://code.jquery.com/jquery-latest.min.js"></script>]]></text>
    	</action>
    </block>
  2. It’s too simple..
    Where do you rewrite Magento Block class here??

    Main difference is that files loaded with method you described:

    <action method="setText">

    will always be at the bottom (last in the head) and you don’t have control in which order they will load.

  3. Tom

    This looks like a great start but I don’t think this method is robust enough. Have you considered adding gzip support from the browser? So browsers that support gzip get the gzip versions and ones without get the regular (minified) version. Something like:

    <?php
       $gExt="";
       if (substr_count($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip')) $gExt=".jgz"; else $gExt="";
    ?>
    <link rel="stylesheet" href="https://yourhost.cloudfront.net/css/a-css-file.css<?php echo $gExt;?>" title="default style" type="text/css" />
    <script type="text/javascript" src="https://yourhost.cloudfront.net/jquery/jquery-1.4.2.min.js<?php echo $gExt;?>"></script>
    
  4. Hi, nice post but question but it really needed to have an extension for this? or you can simply add a code in an xml?.

    Thank you!

    One more thing. There is a typo error in you author description.”Magneto”. :) but all in all you are great.

  5. Works like a charm!

  6. @Janzell
    Extension is needed since I have added new methods (actions) which are called in xml.

    You can add a code in xml like Konstantin said here in comment:

    http://inchoo.net/ecommerce/magento/how-to-add-external-javascript-css-file-to-magento/#comment-19628

    but as you can see it’s not the same thing and my approach is more robust and flexible.

    Thanks for the report for typo error.

  7. Tim

    Quick and easy, worked like a charm. Thank you sir.

  8. @Tim

    You’re Welcome!

  9. Steve

    Works, but breaks when including GET parameters in the script URL. Such as with the Twitter API:
    http://platform.twitter.com/anywhere.js?id=YOUR_API_KEY&v=1
    Take out the parameters, and it works. Quotes do not seem to help. Any ideas?

  10. Steve

    Found the really simple solution, feel silly for not realizing it sooner.
    The presence of the ampersand confuses the XML decoder, makes it think there’s a special entity coming up. Replace it with

    &amp;

    in the XML and all is well.

  11. Does anyone know if it’s possible to control in which order js files appear in head? For example I load jQuery from Google and another tiny js file with one line: jQuery.noConflict() inside, so that jQuery plays nice with Prototype. How can I tell the system to load the “noConflict” js AFTER the jQuery call from Google? Any ideas?

  12. Md. Aminul Islam

    Please change the color of code…..

    Background and main color of code is same [white ]…

    So it create problem.

  13. Md. Aminul Islam

    Sorry now code come properly… may be internet speed problem.

  14. shah

    Hi
    i wanna make a page and add x.html to the content but i don’t know where should i place css and js files that come with that x.html

    it is the head of x.html

    Pricing Grid

    </head

    would you help me?

  15. Alex

    “How wonderful it would be if you could add or remove external, let’s say JavaScript libraries:
    prototype: https://ajax.googleapis.com/ajax/libs/prototype/1.7.0.0/prototype.js

    Yes it would be great, but it doesn’t load Prototype with this extension at first, but right at the end of header. Actually it does the same as:

    <block type="core/text" name="google.jquery">
        <action method="setText">
            <text><![CDATA[<script type="text/javascript" src="http://code.jquery.com/jquery-latest.min.js"></script>]]></text>
        </action>
    </block>
    

    in this case. And if prototype doesn’t load on top, nothing gonna work. Or am I missing something?

  16. Hi, This extension seems very nice to me as it would solve a big problem… I can’t use CDN now to speed up my magento installation … much needed.

    I installed it but I keep getting errors. The Yoast extension is mentionned but even when I disable Yoast one, another extension gets in conflicts. Do you have any idea?

    Here are the errors :

    Invalid method Yoast_CanonicalUrl_Block_Head::addExternalItem(Array
    (
    [0] => external_js
    [1] => http://yui.yahooapis.com/2.8.2r1/build/imageloader/imageloader-min.js
    [2] => Mage_Core_Model_Layout_Element Object
    (
    )

    )
    )

    Trace:
    #0 [internal function]: Varien_Object->__call(‘addExternalItem’, Array)
    #1 [internal function]: Yoast_CanonicalUrl_Block_Head->addExternalItem(‘external_js’, ‘http://yui.yaho…’, Object(Mage_Core_Model_Layout_Element))
    #2 /home/divasen/public_html/boutique/app/code/core/Mage/Core/Model/Layout.php(347): call_user_func_array(Array, Array)
    #3 /home/divasen/public_html/boutique/app/code/core/Mage/Core/Model/Layout.php(213): Mage_Core_Model_Layout->_generateAction(Object(Mage_Core_Model_Layout_Element), Object(Mage_Core_Model_Layout_Element))
    #4 /home/divasen/public_html/boutique/app/code/core/Mage/Core/Model/Layout.php(209): Mage_Core_Model_Layout->generateBlocks(Object(Mage_Core_Model_Layout_Element))
    #5 /home/divasen/public_html/boutique/app/code/core/Mage/Core/Controller/Varien/Action.php(343): Mage_Core_Model_Layout->generateBlocks()
    #6 /home/divasen/public_html/boutique/app/code/core/Mage/Cms/Helper/Page.php(110): Mage_Core_Controller_Varien_Action->generateLayoutBlocks()
    #7 /home/divasen/public_html/boutique/app/code/core/Mage/Cms/Helper/Page.php(52): Mage_Cms_Helper_Page->_renderPage(Object(Mage_Cms_IndexController), ‘home’)
    #8 /home/divasen/public_html/boutique/app/code/core/Mage/Cms/controllers/IndexController.php(45): Mage_Cms_Helper_Page->renderPage(Object(Mage_Cms_IndexController), ‘home’)
    #9 /home/divasen/public_html/boutique/app/code/core/Mage/Core/Controller/Varien/Action.php(418): Mage_Cms_IndexController->indexAction()
    #10 /home/divasen/public_html/boutique/app/code/core/Mage/Core/Controller/Varien/Router/Standard.php(253): Mage_Core_Controller_Varien_Action->dispatch(‘index’)
    #11 /home/divasen/public_html/boutique/app/code/core/Mage/Core/Controller/Varien/Front.php(176): Mage_Core_Controller_Varien_Router_Standard->match(Object(Mage_Core_Controller_Request_Http))
    #12 /home/divasen/public_html/boutique/app/code/core/Mage/Core/Model/App.php(304): Mage_Core_Controller_Varien_Front->dispatch()
    #13 /home/divasen/public_html/boutique/app/Mage.php(596): Mage_Core_Model_App->run(Array)
    #14 /home/divasen/public_html/boutique/index.php(80): Mage::run(”, ‘store’)
    #15 {main}

  17. Dave

    Is there a way to call the https versions of the external files if it’s an https page?

  18. Thanks for this great extension.
    I am new to magento and have no experience with Prototype (although I handle jQuery pretty well).

    So I have the same exact question as Konstantn ( http://inchoo.net/ecommerce/magento/how-to-add-external-javascript-css-file-to-magento/#comment-20374 )
    Is there any way to specify the order of the tags, so that I can use this extention to load jQuery from ajax.googleapis.com _before_ executing jQuery.noConflict() from a local script?

  19. Konstantin

    I am still subscribed to this post and just got notified about a new comment and realized I have something new to add to this discussion.

    First. It’s more reliable to use a local copy of jQuery, as even Google sometimes has downtime or loads files really slow, which results in huge page load times in Magento. Another reason to do this is that you won’t have problems positioning file relative to other JS files.

    Second. Since Magento is so packed with JS and CSS files, you will need to use JS and CSS merging mechanisms to combine them into one chunk of code that loads much faster. Doing this with Magento’s native JS and CSS combine feature breaks jQuery that’s included from your skin/js folder, that’s why I recommend including jQuery from root/js using this code in your page.xml file:

    <action method="addJs"><script>jquery/jquery-1.6.2.min.js</script></action>
    <action method="addJs"><script>jquery/jquery.noConflict.js</script></action>
    

    in this case files are located in public_html/js/jquery/…

    Now enabling JS and CSS merging will work fine. To take even further I recommend using Fooman Speedster Enterprise (it’s free and works on Magento CE just fine) module, as compared to Magento’s native merging it also minifies those merged JS and CSS files with results in lesser file size and load times.

  20. OK – downloaded and installed. Now trying to understand where the extenal Javascript and CSS should be placed. Looking to use external Javascript and CSS from this site:
    http://www.aliimacc.com/TAPageCondo.aspx?condoID=12

  21. Great, just great. Thank you, Thank you, Thank you, Thank you for sharing all this with us.

  22. HI Vedran, how are you? nice work, this extension is just was a needed, I used and is working as a charm.

    Best,
    Alejandro.

  23. This sounds perfect, but soon as i try to call in any external JS file i get the magento error page. In the error report it mentions (looks like a conflict with Mageworx SEO suite). I dont know enough about it to be sure, unless i have done something wrong. Below is part of the error report, any advice would be most welcome :)

    a:5:{i:0;s:227:”Invalid method MageWorx_SeoSuite_Block_Page_Html_Head::addExternalItem(Array
    (
    [0] => external_js
    [1] => http://w.sharethis.com/button/buttons.js
    [2] => Mage_Core_Model_Layout_Element Object
    (
    )

    )
    )”;i:1;s:2032:”#0 [internal function]: Varien_Object->__call(‘addExternalItem’, Array)
    #1 [internal function]: MageWorx_SeoSuite_Block_Page_Html_Head->addExternalItem(‘external_js’, ‘http://w.sharet…’, Object(Mage_Core_Model_Layout_Element))

  24. @Piers, this problem you having is bc you have a error into the overwrite class, check this.
    Other observation is if you have the cache enables don’t forget to clean all of them until try to use the Extension.

    Please check if the module is working fine, you can do it going to admin section, System > Config > Advanced and check if the module is showing in the list.

    Best,
    Alejandro Marroni.
    Magento for Human Beings.

  25. @Alejandro. Thanks for getting back on this.

    Please bear with me, i do not know much about how magento works or php. Learning as i go along.

    Whilst working with this extension i have had the cache turned off, i have cleared it each time as habit.

    Yes the extension is appearing in the list as enabled.

    It seems as soon as i upload the inchoo_xternal.xml file to the layout folder, magento throws up the error and i can no longer view the site.

    I really am at a loss and appreciate all help received.

    Thanks
    Piers

  26. @Piers, Ok, Let me double check the error above And I advise if i found other solution.

    Best,
    Alejandro.

  27. Hi Peeps, it’s me again.

    @Alejandro – Don’t suppose you have had any success regarding my issue?

    @Vedran – Do you have any ideas you could share that might point me in the right direction?

    If i understood the problem a bit better i would know where/how to dig around. But i dont know where to start, as i am dependant on guidance.

    Very grateful for your assistance :)

    Piers

  28. Hey Thanks Vedran, worked effortlessly

  29. @Vishal

    Always glad to help :)

  30. Hi guys. i have been looking at my problem again and it seems there is a conflict in my exception.log with Mageworx SEO suite pro when it is trying to load in the external JS files.

    How can both classes exist together?

    In my exception.log I get: (first couple of lines)

    ‘Varien_Exception’ with message ‘Invalid method MageWorx_SeoSuite_Block_Page_Html_Head::addExternalItem(Array
    (
    [0] => external_js
    [1] =>http://yui.yahooapis.com/2.8.2r1/build/imageloader/imageloader-min.js
    [2] => Mage_Core_Model_Layout_Element Object
    (
    )

    )
    )’ in /home/mytemplate/public_html/lib/Varien/Object.php:652
    Stack trace:
    #0 [internal function]: Varien_Object->__call(‘addExternalItem’, Array)
    #1 [internal function]: MageWorx_SeoSuite_Block_Page_Html_Head->addExternalItem(‘external_js’, ‘http://yui.yaho…’, Object(Mage_Core_Model_Layout_Element))

    Hoping someone can help

    Thanks :)

  31. While this is cool, it won’t work so well if you want to include a CDN JavaScript lib and then a local JS (skin or js) file that depends on the external library since Magento will output the local JS includes before the external.

    You will need to override the getCssJsHtml() method also to make sure the external files are output before the local ones.

  32. Mizpah

    Hi Folks,

    Firstly thanks for this its working well in terms of loading, however I am having an issue controlling the load order.

    I am using an external typekit.js (font replacement, has to be external), and a jquery based menu (local js). A menu’s .js (lets call it menu.js) is loading before typekit.js – and calculating font widths based on the unsubstituted font.Then typekit.js is loading and swapping the fonts, at which point it they are the wrong width.

    The solution is to load my external typekit.js before my menu.js.

    However, no matter where I put my call to typekit.js – in the local.xml, the page.xml, or even in the menu’s own xml file, (above the line that loads menu.js) – it is still loading the file from the via add_external_js method after menu.js.

    How can I control the load order to load the external typekit.js prior to a given local.js file ?

  33. @Mizpah Yeah, that’s exactly the scenario I outlined in my previous comment here.

    I’ve created a more extensive override of Head.php to support a new method for the action method=”” element in layout xml to add JS from CDN:

    addCdnJs()

    With this you can use that before your local JS include using the standard addItem()

    Here is the code on pastebin: http://pastebin.com/K7B9bVW1

  34. Just came across this by accident, but spotted an error in the code.

    Line +66 of Inchoo_Xternal_Block_Html_Head

    parent::addItem($type, $name, $params=null, $if=null, $cond=null);
    

    Should be,

    parent::addItem($type, $name, $params, $if, $cond);
    

    Otherwise, the optional arguments will all be passed as null (regardless of value)

  35. Necolas

    Finally!,
    been looking for 30 minutes for this simple solution… ;)

  36. i can say i do not understand…sigh**
    maybe i need learn more at basic.

  37. @Ellys if you need help, just let us know. Anyway you need to try you first!

  38. del

    Hi, thanks for this extension, but how to add external javascript to admin panel?

  39. Alejandro Marroni

    @del, to add external js into the admin panel first of all you need to creat your own module an add a new xml file into design/adminhtm/default/default/layout. Then use the extension an the place where ever youwant the external js.

    Let me know if ths ca help you, I did this by heard.
    Best,
    Alejandro.

  40. del

    Hi, I did like you said. I have created new module and put xml file into design/adminhtml/default/default/layout with something like this:

    http://pastebin.com/gNB2taUM

    in source code of admin page I saw:

    second action addItem with ‘external_js’ doesn’t work.

    In the frontend i did the same and this is what I saw:

    So on frontend works great but in admin works only with internal scripts…
    I think I must extend some admin block, maybe app\code\core\Mage\Adminhtml\Block\Page\Head.php ….can you help me?

  41. del

    sory, I forgot about code tag

    Hi, I did like you said. I have created new module and put xml file into design/adminhtml/default/default/layout with something like this:

    http://pastebin.com/gNB2taUM

    in source code of admin page I saw:

    <script type="text/javascript" src="https://domain.com/js/nxs/jquery.js"></script>
    

    second action addItem with ‘external_js’ doesn’t work.

    In the frontend i did the same and this is what I saw:

    <script type="text/javascript" src="https:///domain.com/js/nxs/jquery.js"></script>
    <script type="text/javascript" src="http://maps.googleapis.com/maps/api/js?key=&sensor=false" ></script>
    

    So on frontend works great but in admin works only with internal scripts…
    I think I must extend some admin block, maybe app\code\core\Mage\Adminhtml\Block\Page\Head.php ….can you help me?

  42. Hi, yesterday i used this script and as soon as i installed this my front got scattered then i removed manually all its files from all folders. But now in backend products grid is not visible. Any solution to this?

  43. Stareproof

    Thank so much for this! It works great!

    I’m using Magento ver. 1.7.0 so I had to change local to community in Inchoo_Xternal.xml

  44. Nick

    @Stareproof

    Where are you talking about? I’m on 1.7.2 and it does not seem to be working..

  45. Hi All,

    I am new to magento, and not able to get the exact steps to start adding your own javascript file to an admin page of magento admin panel.

    Need to add a js file or do some before form submit of price calculations need to perform some simple maths with weight and silver price related custom attribute text box value to be added in price field with js.

    I saw your extension downloaded the same, however don’t know how to go further.. have seen i this post i need to create xml, however don’t know what are the exact steps can you help.. it will be highly appreciated..

    thanks

    abhishek

  46. janw

    It does not appear to work in Magento 1.8. ‘addExternalItem’ even gives errors

    Invalid method Mage_Page_Block_Html_Head::addExternalItem
  47. Hadi

    How can I adapt this to change based on my language?

    would’ve been great if it had a configuration page though. one we could use based on store view

  48. Stareproof

    @Nick

    In the Inchoo_Xternal.xml file I had to change the “codePool” value from “local” to “community” to get it to work in Magento 1.7.0.

    I changed…

    <config>
        <modules>
            <Inchoo_Xternal>
                <active>true</active>
                <codePool>local</codePool>
            </Inchoo_Xternal>
        </modules>
    </config>
    

    …to…

    <config>
        <modules>
            <Inchoo_Xternal>
                <active>true</active>
                <codePool>community</codePool>
            </Inchoo_Xternal>
        </modules>
    </config>
    

    I hope that helps you :)

  49. Atul Bhalerao

    Hi
    my name is atul and my question is
    How can hide prototype.js only on home page ?

    - Atul Bhalerao

Add Your Comment

Please wrap all source codes with [code][/code] tags.
Top