PHP Alexa Rank Fetcher Class

By  on  

The most well known online website popularity measuring stick appears to be Alexa. Alexa provides a wealth of information on a given website, most notably:

  • Popularity rank (the most important one)
  • Reach
  • In-links
  • Speed

Alexa provides this information in many useful formats, including XML. Using the XML provided by Alexa, we can gain access to Alexa information within our pages. I've created a PHP class to make fetching Alexa data free, quick, and easy. The class comes in a PHP4 version and a PHP5 version.

The Code - PHP4 Version

/* the alexa rank class */
class alexa
{
	/* initial vars */
	var $xml;
	var $values;
	var $alexa_address;

	/* the constructor */
	function alexa($alexa_address,$domain)
	{
		$this->alexa_address = $alexa_address;
		$this->xml = $this->get_data($domain);
		$this->set();
	}

	/* gets the xml data from Alexa */
	function get_data($domain)
	{
		$url = $this->alexa_address.'http://'.$domain;
		$xml = file_get_contents($url);
		return $xml;
	}

	/* set values in the XML that we want */
	function set()
	{
		$this->values['rank'] = (preg_match('/POPULARITY URL="[a-z0-9\\-\\.\\/]{1,}" TEXT="([0-9]{1,12})"/',$this->xml,$regs) ? number_format($regs[1]) : 0);
		$this->values['reach'] = (preg_match('/REACH RANK="([0-9]{1,12})"/',$this->xml,$regs) ? number_format($regs[1]) : 0);
		$this->values['linksin'] = (preg_match('/LINKSIN NUM="([0-9]{1,12})"/',$this->xml,$regs) ? number_format($regs[1]) : 0);
	}

	/* returns the requested value */
	function get($value)
	{
		return (isset($this->values[$value]) ? $this->values[$value] : '"'.$value.'" does not exist.');
	}
}

The Code - PHP5 Version

/* the alexa rank class */
class alexa
{
	/* initial vars */
	var $xml;
	var $values;
	var $alexa_address;

	/* the constructor */
	function alexa($alexa_address,$domain)
	{
		$this->alexa_address = $alexa_address;
		$this->xml = $this->get_data($domain);
		$this->set();
	}

	/* gets the xml data from Alexa */
	function get_data($domain)
	{
		$url = $this->alexa_address.'http://'.$domain;
		$xml = simplexml_load_file($url) or die('Cannot retrieve feed');
		return $xml;
	}

	/* set values in the XML that we want */
	function set()
	{
		$this->values['rank'] = ($this->xml->SD->POPULARITY['TEXT'] ? number_format($this->xml->SD->POPULARITY['TEXT']) : 0);
		$this->values['reach'] = ($this->xml->SD->REACH['RANK'] ? number_format($this->xml->SD->REACH['RANK']) : 0);
		$this->values['linksin'] = ($this->xml->SD->LINKSIN['NUM'] ? number_format($this->xml->SD->LINKSIN['NUM']) : 0);
	}

	/* returns the requested value */
	function get($value)
	{
		return (isset($this->values[$value]) ? $this->values[$value] : '"'.$value.'" does not exist.');
	}
}

Using cURL

If you'd rather use the cURL library, you can simply modify the get_data() function:

/* gets the XML data from Alexa */
function get_data($domain)
{
	$url = $this->alexa_address.'http://'.$domain;
	$ch = curl_init();
	$timeout = 5;
	curl_setopt($ch,CURLOPT_URL,$url);
	curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);
	curl_setopt($ch,CURLOPT_CONNECTTIMEOUT,$timeout);
	$xml = curl_exec($ch);
	curl_close($ch);
	return $xml;
}

The Usage

Provide two paramenters: the path to the XML file (minus the domain) and the domain.

/* retrieve & display rank */
$alexa_connector = new alexa('http://alexa.com/xml/dad?url=','digg.com'); // domain only!
echo 'Rank :: '.$alexa_connector->get('rank'); // returns 118
echo '';
echo 'Reach :: '.$alexa_connector->get('reach'); // returns 95
echo '';
echo 'Links In :: '.$alexa_connector->get('linksin'); // returns 34,414

Do you have any suggestions for this class?

Recent Features

  • By
    Page Visibility API

    One event that's always been lacking within the document is a signal for when the user is looking at a given tab, or another tab. When does the user switch off our site to look at something else? When do they come back?

  • By
    Camera and Video Control with HTML5

    Client-side APIs on mobile and desktop devices are quickly providing the same APIs.  Of course our mobile devices got access to some of these APIs first, but those APIs are slowly making their way to the desktop.  One of those APIs is the getUserMedia API...

Incredible Demos

  • By
    Create Twitter-Style Dropdowns Using jQuery

    Twitter does some great stuff with JavaScript. What I really appreciate about what they do is that there aren't any epic JS functionalities -- they're all simple touches. One of those simple touches is the "Login" dropdown on their homepage. I've taken...

  • By
    jQuery Comment Preview

    I released a MooTools comment preview script yesterday and got numerous requests for a jQuery version. Ask and you shall receive! I'll use the exact same CSS and HTML as yesterday. The XHTML The CSS The jQuery JavaScript On the keypress and blur events, we validate and...

Discussion

  1. I did not know Alexia. It’s a good site. Thank’s for the suggest.

    About the class why not put the address site direct in the function get_data? If the address change you only need change in only place. In the constructor you need change in every call of this class.

  2. I waffled between putting it inside the class or giving it to the constructor.

    In the end, I chose the constructor to make the class more “flexible,” so to speak. There are multiple URLs you can retrieve this information from.

  3. Hello …
    thank you for this script … but the result didn’t contain the alexa rank …

    it looks like :
    Rank :: 0
    Reach :: 745,382
    Links In :: 0

    any explain ….
    thanks anyway for your great effort

  4. Not all sites are given a rank Osama. What should it be?

  5. I am having some kind of error

    firstly in my site i am having php5.0 version, so i tried to use php5.0 (alexia rating) codes given above
    but i get error on this simplexml_load_file function, saying undefined!

    anyways so then i used php4.0 codes, it worked fine, but giving error again at line 31: Warning: preg_match() [function.preg-match]: Unknown modifier ‘]’

    i just copied these codes, what might be the reason?
    Please be a little descriptive, since i have a little knowledge on this object-oriented thing in php.

  6. oh i forgot to say

    the line 31 is this line

    $this->values['rank'] = (preg_match('/POPULARITY URL="([a-z-0-9-./]{1,})" TEXT="([0-9]{1,12})"/',$this->xml,$regs) ? number_format($regs[1]) : 0);
    

    which is having the error

  7. Thank you for the heads up Parijat. WordPress mangled my code. I’ve completely replaced the previous PHP4 “set” function above so use that. You’ll notice many more forward slashes.

  8. hi david

    thx for solving that thing. its working fine now and so i can use it with my top-site.

    Thank you

    For others who r using it:

    One small Tip:

    if you need to make the thing dynamic, replace the constructor.

    Replace:

    $alexa_connector = new alexa('http://alexa.com/xml/dad?url=','digg.com'); // domain only!
    

    with this two line

    $site = $_GET['site'];
    $alexa_connector = new alexa('http://alexa.com/xml/dad?url=',$site); // domain only!
    

    you pass the domain name as get parameter.

    Alternatively, you can use POST method too.

    Hope that helps you.

  9. Kevin

    Hey David,

    How easy would it be to deposit the data into a MySQL database?

    Thanks for a cool tool!

  10. @Kevin: Extremely easy — you’d just add the MySQL code to my code above.

  11. Yeah.but how can I parse the tag and get the text?

  12. @neekey: It’s all above…

  13. I mean I want to get more tags like ADDR,LANG,SPEED, and so on.
    could you do it?Thank you very much.
    It is really a useful lib :)

  14. Absolutely brilliant! Thank you for this class – it’s a real help. :-)

  15. Dave

    Thank you for the brilliant class you’ve made. I just want to suggest if you can make it by URL/page not by domain only. Thank you :-)

  16. It seems as though Alexa have changed their method and no longer provide this data for free, but rather by payment through Amazon servers. Is that correct??

  17. Kevin

    Eytan, you might be right: http://aws.amazon.com/awis/

    Question is, how is my Firefox SearchStatus Addon still working?

  18. jason

    Is CURL a better option? What are the pros/cons? Do you have an opinion?

  19. This is a great post, fortunately 70% of the time of website owner is consumed in experimenting towards increasing page rank and alexa rank. To start with increasing page rank one must start with downloading Alexa toolbar for IE or firefox on as many system possible. as a second step alexa widget on every page of your website, by this way every webpage opened is counted while calculating rank inspite is user does not have alexa toolbar installed knowtheworldaround.com

  20. The code below cannot fetch the data from alexa –
    $alexa_connector = new alexa(‘http://alexa.com/xml/dad?url=’

    I used PHP5 version and replaced the above code with it. Will try to modify the code and use it on http://seoadsense.free2step.com/index.php/seo-tools/page-rank-checker/ and see how it goes.

  21. Ahmad

    it’s not working anymore :(

    anyone got a new code for it ?

  22. Do you know information about names of field in XML data that Alexa send? Here it is a part of XML data

  23. Oops.. It looks like your comment engine cut XML data.. Try again

    <ALEXA VER=”0.9″ URL=”google.com/” HOME=”0″ AID=”=”>
    <RLS PREFIX=”http://” more=”255″>
    <RL HREF=”www.zoneedit.com/” TITLE=”ZoneEdit”/>
    <RL HREF=”www.tzo.com/” TITLE=”Tzo.com The Reliable Dynamic Dns Service”/>
    </RLS>
    <SD TITLE=”A” FLAGS=”DMOZ”>

  24. i think the script its not working anymore, because alexa.com use pay subscription for this kind of service

  25. Script not working
    return Warning: file_get_contents(): HTTP request failed! HTTP/1.0 404 Not Found

  26. ok, if they want $$$ for xml… we can just download the whole page containing the information ;).. but there must be some other way, because there are free toolbars which showing the alexa numbers without parsingthe whole page…

  27. I tried this code and its working rather sweetly


    function Alexa($domain) {
    $remote_url = 'http://data.alexa.com/data?cli=10&dat=snbamz&url='.trim($domain);
    $search_for = '', $str[1]));
    $str = explode('TEXT="', $str);
    return number_format($str[1]);
    }
    echo "Alexa ranking: " . Alexa("http://www.google.com");

  28. Hi,

    I have made a slightly different version.
    I am interested in evaluating a list of sites printing for each site the Alexa rank popularity.

    function AlexaRank( $url )
    {
    
    preg_match( '##si', file_get_contents('http://data.alexa.com/data?cli=10&dat=s&url=' . $url), $p );
    return ( $p[2] ) ? number_format( intval($p[2]) ):0;
    }
    
       $file= file_get_contents("http:///www.yoursite.com/sitelist.txt");
    
       // Place each line of $userfile into array
       $domains = explode("\n",$file);
    
     foreach ( $domains as $domain )
    {
    
    echo $domain, ' - Rank', AlexaRank( $domain ), ' - ' , "". "whois",  ' - ',PHP_EOL;
    
    
    }
    
  29. hmmm….

    I noticed some errors in the function set() so removed the number format operator.
    It returns the back links, but not the RANK or REACH value, which is present in the actual XML…

    my updated class and call:

    //
    /* the alexa rank class */
    class alexa
    {
    	/* initial vars */
    	var $xml;
    	var $values;
    	var $alexa_address;
    
    	/* the constructor */
    	function alexa($alexa_address,$domain)
    	{
    		$this->alexa_address = $alexa_address;
    		$this->xml = $this->get_data($domain);
    		$this->set();
    	}
    
    	/* gets the xml data from Alexa */
    	function get_data($domain)
    	{
    		$url = $this->alexa_address.'http://'.$domain;
    		$xml = simplexml_load_file($url) or die('Cannot retrieve feed');
    		return $xml;
    	}
    
    	/* set values in the XML that we want */
    	function set()
    	{
    		$this->values['rank'] = ($this->xml->SD->POPULARITY['TEXT'] ? ($this->xml->SD->POPULARITY['TEXT']) : 0);
    		
    		$this->values['owner'] = ($this->xml->SD->OWNER['NAME'] ? ($this->xml->SD->OWNER['NAME']) : 0);
    		$this->values['email'] = ($this->xml->SD->EMAIL['ADDR'] ? ($this->xml->SD->EMAIL['ADDR']) : 0);
    		$this->values['reach'] = ($this->xml->SD->REACH['RANK'] ? ($this->xml->SD->REACH['RANK']) : 0);
    		$this->values['linksin'] = ($this->xml->SD->LINKSIN['NUM'] ? ($this->xml->SD->LINKSIN['NUM']) : 0);
    	}
    
    	/* returns the requested value */
    	function get($value)
    	{
    		return (isset($this->values[$value]) ? $this->values[$value] : '"'.$value.'" does not exist.');
    	}
    }
    echo "";
    echo "Alexa rank details: ";
    
    /* retrieve & display rank */
    $alexa_connector = new alexa('http://data.alexa.com/data?cli=10&dat=snbamz&url=','google.com'); // domain only!
    echo 'Rank :: '.$alexa_connector->get('rank').""; // returns 118
    echo $alexa_connector->get('owner');
    echo 'Reach :: '.$alexa_connector->get('reach').""; // returns 95
    echo $alexa_connector->get('email');
    echo 'Links In :: '.$alexa_connector->get('linksin').""; // returns 34,414
    echo "";
    //
    

    Any ideas?

  30. hmm that didnt work to well!

  31. so this is the xml output: i hope! if not you can see it at

    http://data.alexa.com/data?cli=10&dat=snbamz&url=snowsh.com

  32. Hi, I have a question.
    suppose I am displaying xml alexa rank in my webpage, how do I display list of “websites” similar to my alexa rank.

    anticipate for your response.

    thank you..

  33. similar mean
    +1,+2 or -1 , -2 ranking website list.

    like my site alexa rank is 4445
    similar site for my site is
    aaa.com – 4442
    bbb.com – 4443
    aac.com – 4444
    aab.com – 4446
    aax.com – 4447
    aad.com – 4448

  34. Here’s my class in action: http://www.swordfoxdesign.co.nz/resources/alexa-rank-tool/

    class alexa
    {
    	/* initial vars */
    	var $alexa_address='http://data.alexa.com/data?cli=10&dat=s&url=';
    	
    	function wp_xml2array($__url){
    	    $xml_values = array();
    	    $contents = file_get_contents($__url);
    	    $parser = xml_parser_create('');
    	    if(!$parser)
    	        return false;
    	
    	    xml_parser_set_option($parser, XML_OPTION_TARGET_ENCODING, 'UTF-8');
    	    xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0);
    	    xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1);
    	    xml_parse_into_struct($parser, trim($contents), $xml_values);
    	    xml_parser_free($parser);
    	    if (!$xml_values)
    	        return array();
    	   
    	    $xml_array = array();
    	    $last_tag_ar =& $xml_array;
    	    $parents = array();
    	    $last_counter_in_tag = array(1=>0);
    	    foreach ($xml_values as $data)
    	    {
    	        switch($data['type'])
    	        {
    	            case 'open':
    	                $last_counter_in_tag[$data['level']+1] = 0;
    	                $new_tag = array('name' => $data['tag']);
    	                if(isset($data['attributes']))
    	                    $new_tag['attributes'] = $data['attributes'];
    	                if(isset($data['value']) && trim($data['value']))
    	                    $new_tag['value'] = trim($data['value']);
    	                $last_tag_ar[$last_counter_in_tag[$data['level']]] = $new_tag;
    	                $parents[$data['level']] =& $last_tag_ar;
    	                $last_tag_ar =& $last_tag_ar[$last_counter_in_tag[$data['level']]++];
    	                break;
    	            case 'complete':
    	                $new_tag = array('name' => $data['tag']);
    	                if(isset($data['attributes']))
    	                    $new_tag['attributes'] = $data['attributes'];
    	                if(isset($data['value']) && trim($data['value']))
    	                    $new_tag['value'] = trim($data['value']);
    	
    	                $last_count = count($last_tag_ar)-1;
    	                $last_tag_ar[$last_counter_in_tag[$data['level']]++] = $new_tag;
    	                break;
    	            case 'close':
    	                $last_tag_ar =& $parents[$data['level']];
    	                break;
    	            default:
    	                break;
    	        };
    	    }
    	    return $xml_array;
    	}
    	
    	//
    	// use this to get node of tree by path with '/' terminator
    	//
    	function wp_get_value_by_path($__xml_tree, $__tag_path)
    	{
    	    $tmp_arr =& $__xml_tree;
    	    $tag_path = explode('/', $__tag_path);
    	    foreach($tag_path as $tag_name)
    	    {
    	        $res = false;
    	        foreach($tmp_arr as $key => $node)
    	        {
    	            if(is_int($key) && $node['name'] == $tag_name)
    	            {
    	                $tmp_arr = $node;
    	                $res = true;
    	                break;
    	            }
    	        }
    	        if(!$res)
    	            return false;
    	    }
    	    return $tmp_arr;
    	}
    	
    	function getRank($url)
    	{
    		$arr = $this->wp_xml2array($this->alexa_address.$url);
    		$arr2= $this->wp_get_value_by_path($arr, 'ALEXA');
    		
    		$arr3=($arr2[2][0]['attributes']);
    		$rank=$arr3['TEXT'];
    		
    		$rank=($rank=='' ? 'Not ranked yet' : $rank);
    		
    		return $rank;
    	}
    }
    

    Call using this:

    $alexa = new Alexa();
    		
    $rank = $alexa->getRank(str_replace('http://', '', $url));
    
  35. Sorry, i didnt added code tag… lawl..


    function AlexaRank( $url )
    {
    preg_match( '##si', file_get_contents('http://data.alexa.com/data?cli=10&dat=s&url=' . $url), $p );
    return ( $p[2] ) ? number_format( intval($p[2]) ):0;
    }

    Here

    http://www.igloro.info/en/pagerank.html

  36. Great post.
    Exactly what I was looking for my website

  37. Thanks for this script !
    It seems not working anymore. Do you have an idea of the reason ? Is it possible to fix it ?

  38. sana

    :(

Wrap your code in <pre class="{language}"></pre> tags, link to a GitHub gist, JSFiddle fiddle, or CodePen pen to embed!