Blog

Google Analytics HTTP API

Posted on

Sometimes a low-tech approach can be useful.

While working on an SEO related project, I encountered a problem with Google’s recommended authorization standard (Oauth2) where authorization tokens for Google Analytics accounts were being invalidated after their first use. I got around this by developing a client from an open source PHP class that uses the less secure, but in my situation, more reliable “HTTP Auth” ClientLogin authorization method to access Google’s Analytics API.

The client uses a direct HTTP authorization via Google credentials to log in to the Analytics account and then retrieves, via curl, and parses an XML feed based on RESTful style query. Please note that this is neither the most secure or recommended method of accessing Google’s API and there is no guarantee that they will continue to support the method with future API releases.

The attachment contains the PHP class and a test client for exploration. Feel free to modify and use as needed.

View the Google Analytics HTTP API at my github repository.

Google Analytics HTTP Client


Users of software offered on this website, and those given permission for its use within software that they distribute, are bound by the following disclaimer of warranty:DISCLAIMER OF WARRANTY AND LIMITATION OF LIABILITY

THIS SOFTWARE IS FURNISHED “AS IS”. WITHOUT WARRANTIES, EXPRESS OR IMPLIED, THAT THE SOFTWARE IS FREE OF ERROR, OR IS CONSISTENT WITH ANY PARTICULAR STANDARD OF MERCHANTABILITY, OR THAT IT WILL MEET USER’S REQUIREMENTS FOR ANY PARTICULAR APPLICATION. I ACCEPT NO RESPONSIBILITY FOR ANY MATHEMATICAL OR TECHNICAL LIMITATIONS OF THE PROCEDURES AND FUNCTIONS WHICH MAKE UP THE SOFTWARE. WITHOUT ADDITIONAL THOROUGH TESTING BY USER, THE SOFTWARE SHOULD NOT BE RELIED ON FOR SOLVING A PROBLEM WHOSE INCORRECT SOLUTION COULD RESULT IN INJURY TO A PERSON OR LOSS OF PROPERTY. I SHALL NOT IN ANY EVENT BE LIABLE FOR ANY DAMAGES, WHETHER DIRECT OR INDIRECT, SPECIAL OR GENERAL, CONSEQUENTIAL OR INCIDENTAL, ARISING FROM USE OF THE SOFTWARE. USE OF THE SOFTWARE IS ENTIRELY AT USER’S OWN RISK.


[PHP] Recursive Array Intersect Key

Posted on

A recursive version of the PHP Function: array_intersect_key.

    /** 
    * Recursively computes the intersection of arrays using keys for comparison.
    * 
    * @param   array $array1 The array with master keys to check.
    * @param   array $array2 An array to compare keys against.
    * @return  array associative array containing all the entries of array1 which have keys that are present in array2.
    **/
    function array_intersect_key_recursive(array $array1, array $array2) {
        $array1 = array_intersect_key($array1, $array2);
        foreach ($array1 as $key => &$value) {
            if (is_array($value) && is_array($array2[$key])) {
                $value = array_intersect_key_recursive($value, $array2[$key]);
            }
        }
        return $array1;
    }

[PHP] Array Max Filter by Key

Posted on

PHP’s array_filter function is great way of manipulating arrays. Since PHP version 5.3, the callback function argument can include closures – references to external variables, increasing the utility of array_filter. Today, I came across a situation where I wanted to manipulate an associative array by filtering its elements using a regular expression match on the index so I wrote the following function that will hopefully benefit others looking for this solution.

    /** 
    * Finds and optionally filters the index of the highest value in an array.
    * 
    * @author  Akin Williams <aowilliams@arstropica.com>
    * 
    * @param   array $array Array to be filtered
    * @param   string $pattern Optional, regular expression pattern for index filter.
    * @return  bool|string|int index of element with highest value matching pattern or false if no match
    **/
    function array_max_index_filter($array, $pattern=null) {
        $output = false;
        if (is_array($array) && (empty($array) === false)) {
            $filtered_keys = array_filter(array_keys($array), function ($el) use (&$pattern) { return ($pattern) ? preg_match($pattern, $el) : true; });
            $filtered_array = array_intersect_key($array, array_flip($filtered_keys));
            if (empty($filtered_array) === false) {
                $output = current(array_keys($filtered_array, max($filtered_array)));
            }
        }
        return $output;
    }

[PHP] Recursive Key Search

Posted on

After unsuccessfully searching for a way to locate a key in a multidimensional array, I decided to write a function that will do this and return the path, element or value associated with the key.

    /**
    * Recursively searches a multidimensional array for a key and optional value and returns the path as a string representation or subset of the array or a value.
    *
    * @author  Akin Williams <aowilliams@arstropica.com>
    *
    * @param   int|string $needle Key
    * @param   array $haystack Array to be searched
    * @param   bool $strict Optional, limit to keys of the same type. Default false.
    * @param   string $output Optional, output key path as a string representation or array subset, ('array'|'string'|'value'). Default array.
    * @param   bool $count Optional, append number of matching elements to result. Default false.
    * @param   int|string $value Optional, limit results to keys matching this value. Default null.
    * @return  array Array containing matching keys and number of matches
    **/
    function multi_array_key_search($needle, $haystack, $strict=false, $output='array', $count=false, $value=null) {
        // Sanity Check
        if(!is_array($haystack))
            return false;

        $resIdx='matchedIdx';
        $prevKey = "";
        $keys = array();
        $num_matches = 0;

        $numargs = func_num_args();
        if ($numargs > 6){
            $arg_list = func_get_args();
            $keys = $arg_list[6];
            $prevKey = $arg_list[7];
        }

        $keys[$resIdx] = isset($keys[$resIdx]) ? $keys[$resIdx] : 0;

        foreach($haystack as $key => $val) {
            if(is_array($val)) {
                if ((($key === $needle) && is_null($value)) || (($key === $needle) && ($val[$key] == $value) && $strict === false) || (($key === $needle) && ($val[$key] === $value) && $strict === true)){
                    if ($output == 'value'){
                        $keys[$keys[$resIdx]] = $val;
                    } else {
                        $keys[$keys[$resIdx]] = $prevKey . (isset($keys[$keys[$resIdx]]) ? $keys[$keys[$resIdx]] : "") . "["$key"]";
                    }
                    $keys[$resIdx] ++;
                }
                $passedKey = $prevKey . "["$key"]";;
                $keys = multi_array_key_search($needle, $val, $strict, $output, true, $value, $keys, $passedKey);
            } else {
                if ((($key === $needle) && is_null($value)) || (($key === $needle) && ($val == $value) && $strict === false) || (($key === $needle) && ($val === $value) && $strict === true)){
                    if ($output == 'value'){
                        $keys[$keys[$resIdx]] = $val;
                    } else {
                        $keys[$keys[$resIdx]] = $prevKey . (isset($keys[$keys[$resIdx]]) ? $keys[$keys[$resIdx]] : "") . "["$key"]";
                    }
                    $keys[$resIdx] ++;
                }
            }
        }
        if ($numargs < 7){
            $num_matches = (count($keys) == 1) ? 0 : $keys[$resIdx];
            if ($count) $keys['num_matches'] = $num_matches;
            unset($keys[$resIdx]);
            if (($output == 'array') && $num_matches > 0){
                if (is_null($value)) {
                    $replacements = multi_array_key_search($needle, $haystack, $strict, 'value', false);
                }
                $arrKeys = ($count) ? array('num_matches' => $num_matches) : array();
                for ($i=0; $i < $num_matches; $i ++){
                    $keysArr = explode(',', str_replace(array('][', '[', ']'), array(',', '', ''), $keys[$i]));
                    $json = "";
                    foreach($keysArr as $nestedkey){
                        $json .= "{" . $nestedkey . ":";
                    }
                    if (is_null($value)){
                        $placeholder = time();
                        $json .= ""$placeholder"";
                    } else {
                        $json .= ""$value"";
                    }
                    foreach($keysArr as $nestedkey){
                        $json .= "}";
                    }
                    $arrKeys[$i] = json_decode($json, true);
                    if (is_null($value)) {
                        array_walk_recursive($arrKeys[$i], function (&$item, $key, &$userdata) {
                            if($item == $userdata['placeholder'])
                                $item = $userdata['replacement'];
                        }, array('placeholder' => $placeholder, 'replacement' => $replacements[$i]));
                    }
                }
                $keys = $arrKeys;
            }
        }
        return $keys;
    }

WP RSS Syndication Client

Posted on

WP RSS Syndication Client plugin displays posts from a remote WordPress blog RSS feed via shortcode. The plugin has some basic theme integration functionality allowing positioning on front page or posts page.

View the WP RSS Syndication Client at my github repository.


Users of software offered on this website, and those given permission for its use within software that they distribute, are bound by the following disclaimer of warranty:DISCLAIMER OF WARRANTY AND LIMITATION OF LIABILITY

THIS SOFTWARE IS FURNISHED “AS IS”. WITHOUT WARRANTIES, EXPRESS OR IMPLIED, THAT THE SOFTWARE IS FREE OF ERROR, OR IS CONSISTENT WITH ANY PARTICULAR STANDARD OF MERCHANTABILITY, OR THAT IT WILL MEET USER’S REQUIREMENTS FOR ANY PARTICULAR APPLICATION. I ACCEPT NO RESPONSIBILITY FOR ANY MATHEMATICAL OR TECHNICAL LIMITATIONS OF THE PROCEDURES AND FUNCTIONS WHICH MAKE UP THE SOFTWARE. WITHOUT ADDITIONAL THOROUGH TESTING BY USER, THE SOFTWARE SHOULD NOT BE RELIED ON FOR SOLVING A PROBLEM WHOSE INCORRECT SOLUTION COULD RESULT IN INJURY TO A PERSON OR LOSS OF PROPERTY. I SHALL NOT IN ANY EVENT BE LIABLE FOR ANY DAMAGES, WHETHER DIRECT OR INDIRECT, SPECIAL OR GENERAL, CONSEQUENTIAL OR INCIDENTAL, ARISING FROM USE OF THE SOFTWARE. USE OF THE SOFTWARE IS ENTIRELY AT USER’S OWN RISK.