The current Google Analytics Dashboard for WordPress integrates no Opt-Out to disable tracking, which is required in Europe. Here is a workaround for that.
Paste this into your theme function.php.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
if ( !is_user_logged_in() && class_exists('GADWP_Manager') ) { add_action('wp_head', 'ga_optout_script', 1); } function ga_optout_script(){ // Read GA Dashboard Settings $options = (array) json_decode(get_option('gadash_options')); // Get GA Dashboard profiles foreach($options['ga_dash_profile_list'] as $profile){ $ga_ua_profile[$profile[1]] = $profile[2]; } // Get active Analytics profile for the current website $active = $options['ga_dash_tableid_jail']; $activeUA = $ga_ua_profile[$active]; // Add opt-out script + active UA echo "<script> var gaProperty = '".$activeUA."'; var disableStr = 'ga-disable-' + gaProperty; if (document.cookie.indexOf(disableStr + '=true') > -1) { window[disableStr] = true; } function gaOptout() { document.cookie = disableStr + '=true; expires=Thu, 31 Dec 2099 23:59:59 UTC; path=/'; window[disableStr] = true; } </script>"; } |
Then add this to your data privacy document:
1 |
<a href="javascript:gaOptout()">Disable Google Analytics tracking</a> |
When the defer attribute is present in the script tag, it specifies that the script is executed when the page has finished parsing. A requirement that is enforced by Google for example (Page-Speed ranking).
Currently the WordPress wp_enqueue_script provides no easy way to add new attributes, but there is a way around that :)
The below hack / filter needs to be added to your theme function.php. The filter should be your preferred solution, as the clean_url filter has been deprecated.
Make sure that your website / theme is still loading after adding these changes. If needed you can add more exceptions, as I did for jQuery.
Hack for WordPress before 4.1
1 2 3 4 5 6 7 8 |
if(is_admin() === FALSE){ function defer_parsing_of_js ( $url ) { if ( FALSE === strpos( $url, '.js' ) ) return $url; if ( strpos( $url, 'jquery.js' ) ) return $url; return "$url' defer "; } add_filter( 'clean_url', 'defer_parsing_of_js', 11, 1 ); } |
Filter for WordPress 4.1+
Updated: 26.04.2015 – using clean Regexp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
if(is_admin() === FALSE){ function add_js_defer($tag, $handle, $src){ if( strpos( $tag, 'jquery.js' ) ) return $tag; preg_match_all('/([\w\-.:]+)\s*=\s*("[^"]*"|\'[^\']*\'|[\w\-.:]+)/i', $tag, $match); $newtag = "<script "; foreach($match[1] as $key=> $val){ $newtag .= $val."=".$match[2][$key]." "; } $newtag .= "defer></script>"; return $newtag.PHP_EOL; } add_filter( 'script_loader_tag', 'add_js_defer', 11, 1 ); } |
Compressing your content saves bandwidth and improves render time, particular on devices with slow internet connections. Compression allows your web server to provide smaller file sizes that load faster for your visitors. Compression of your HTML and CSS files with gzip typically saves around 50 to 70 % of the file size.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
# compress text, html, javascript, css, xml: AddOutputFilterByType DEFLATE text/plain AddOutputFilterByType DEFLATE text/html AddOutputFilterByType DEFLATE text/xml AddOutputFilterByType DEFLATE text/css AddOutputFilterByType DEFLATE application/xml AddOutputFilterByType DEFLATE application/xhtml+xml AddOutputFilterByType DEFLATE application/rss+xml AddOutputFilterByType DEFLATE application/javascript AddOutputFilterByType DEFLATE application/x-javascript # Or, compress certain file types by extension: <files *.html> SetOutputFilter DEFLATE </files> |
1 2 3 4 5 6 7 8 9 10 11 12 13 |
gzip on; gzip_comp_level 2; gzip_http_version 1.0; gzip_proxied any; gzip_min_length 1100; gzip_buffers 16 8k; gzip_types text/plain text/html text/css application/x-javascript text/xml application/xml application/xml+rss text/javascript; # Disable for IE < 6 because there are some known problems gzip_disable "MSIE [1-6].(?!.*SV1)"; # Add a vary header for downstream proxies to avoid sending cached gzipped files to IE6 gzip_vary on; |
A good candidate is the WP Far Future Expiration Plugin ,which not only activates GZIP compression but adds file expiration for various static file types.
Link
Check speed improvement before and after
Will be adding some basic information about using the current Google API with the PHP SDK, this includes Google+, Youtube and other services. For setting up the actual API access see the Google documentation and Google Developer Console
1 2 3 4 5 6 7 8 9 10 11 12 |
require _DIR_TO_AUTOLOAD_SDK_.'/google_sdk/autoload.php'; // Required Information // OAuth 2.0 $google_client_id = _GOOGLE_CLIENT_ID_; $google_client_secret = _GOOGLE_CLIENT_SECRET_; // Public API-Access $google_redirect_url = 'http://yourdomain.com/google_login/?option=do_login'; // API-key for a server application! $google_developer_key = _GOOGLE_DEVELOPER_KEY_; |
1 2 3 4 5 6 7 |
$gClient = new Google_Client(); $gClient->setAccessType('offline'); $gClient->setApplicationName('Application Name'); $gClient->setClientId($google_client_id); $gClient->setClientSecret($google_client_secret); $gClient->setRedirectUri($google_redirect_url); $gClient->setDeveloperKey($google_developer_key); |
1 2 3 4 5 6 7 8 9 10 |
$gClient->setScopes(array( 'https://www.googleapis.com/auth/plus.me', 'https://www.googleapis.com/auth/plus.login', 'https://www.googleapis.com/auth/userinfo.email', 'https://www.googleapis.com/auth/userinfo.profile', 'https://gdata.youtube.com', 'https://www.googleapis.com/auth/youtube.readonly', 'https://www.googleapis.com/auth/youtubepartner' ) ); |
1 |
$plus = new Google_Service_Plus($gClient); |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
session_start(); // A simple check for the login to get a fresh token if($_GET['option'] == "do_login" && empty($_SESSION['google_token'])){ // Check for redirect from Google & Auth if (empty($_GET['code'])) { // Create Auth redirect header('Location: '.$gClient->createAuthUrl()); } else { $gClient->authenticate($_GET['code']); $access_token = $gClient->getAccessToken(); //Store the token in a session or your database for later use $_SESSION['google_token'] = $access_token; } } // You have already logged in if(!empty($_SESSION['google_token'])){ $gClient->setAccessToken($_SESSION['google_token']); } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
// Making sure we have a valid access token if($gClient->getAccessToken()) { try{ // Get your activities $optParams = array('maxResults' => 100); $activities = $plus->activities->listActivities('me', 'public', $optParams); print_r($activities); } } catch (Google_ServiceException $e) { $htmlBody .= sprintf('<p>A service error occurred: <code>%s</code></p>', htmlspecialchars($e->getMessage())); } catch (Google_Exception $e) { $htmlBody .= sprintf('<p>An client error occurred: <code>%s</code></p>', htmlspecialchars($e->getMessage())); } |
Will be adding some basic information about using the current Facebook API with the PHP SDK. Have been updating a lot of old API integrations over the past 2 months and finally solved many badly documented areas of the new API. Will be updating this in the future, as I dive deeper into the latest API changes.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
require_once _DIR_TO_AUTOLOAD.'/facebook_sdk/autoload.php'; use Facebook\FacebookSession; use Facebook\FacebookRedirectLoginHelper; use Facebook\FacebookRequest; use Facebook\FacebookResponse; use Facebook\FacebookSDKException; use Facebook\FacebookRequestException; use Facebook\FacebookAuthorizationException; use Facebook\GraphObject; use Facebook\Entities\AccessToken; use Facebook\HttpClients\FacebookCurlHttpClient; use Facebook\HttpClients\FacebookHttpable; |
Depending on what you want to do with the API, the above needs to be adjusted. Check the Facebook API documentation for more details.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 |
// Session should be started after all files have been included session_start(); // init app with app id and secret FacebookSession::setDefaultApplication( _FB_APP_ID_, _FB_APP_SECRET_ ); // login helper with redirect_uri $helper = new FacebookRedirectLoginHelper( 'http://yourdomain.com/FB_LOGIN/'); // Check for Facebook redirect & retrieve session try { $session = $helper->getSessionFromRedirect(); } catch( FacebookRequestException $ex ) { // When Facebook returns an error } catch( Exception $ex ) { // When validation fails or other local issues } if ( isset( $session ) ) { /* Store the session for later reuse, in this case even getting a long lived session. You should store this in your database. The session can be reused with: $session = new FacebookSession($_SESSION['long']->getToken()); */ if(empty($_SESSION['long'] )){ $_SESSION['long'] = $session->getLongLivedSession(); } // graph api request for user data try { $user_profile = (new FacebookRequest( $session, 'GET', '/me' ))->execute()->getGraphObject(GraphUser::className()); echo "Name: " . $user_profile->getName(); } catch(FacebookRequestException $e) { echo "Exception occured, code: " . $e->getCode(); echo " with message: " . $e->getMessage(); } } else { // show login url if no session available // request special permissions, optional. $params = array( 'manage_pages', 'publish_pages','publish_actions','user_videos' ); echo '<a href="' . $helper->getLoginUrl($params ) . '">Login</a>'; } |
I had a problem with the tag pagination throwing 404 errors and was forced to integrate a custom query into the 404 page, while fixing the rewrite rules ;)
This is how you force a different HTTP response header with WordPress, in this case a simple HTTP/1.1 200 OK.
1 2 |
$GLOBALS['wp_query']->is_404 = false; status_header( 200 ); |
Some tweaking to add your own classes to the body tag
1 2 3 4 5 6 7 |
add_filter( 'body_class', 'my_class_names' ); function my_class_names( $classes ) { $classes[] = "archive tag " ; return $classes; } |
“countUp.js is a dependency-free, lightweight JavaScript “class” that can be used to quickly create animations that display numerical data in a more interesting way.”
1 |
$average_of_myfoos = array_sum($myfoos) / count($myfoos); |
1 2 |
var sum = myfoos.reduce(function(a, b) { return a + b; }); var avg = sum / myfoos.length; |
As part of our complete network upgrade, portalZINE.TV gets a complete facelift as well. The whole website has been streamlined in preparation for the new season.
1. Add Vimeo iframe
1 |
<iframe id="vimPlayer" width="500" height="281" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe> |
2. Load Froogaloop and add some Javascript
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
var vimID = ""; var playerID = "vimPlayer"; $("#vimPlayer").attr("src", "//player.vimeo.com/video/"+vimID+"?api=1&title=0&byline=0&portrait=0&color=f00010&player_id="+playerID); Froogaloop(jQuery('#'+playerID)[0]).addEvent('ready', ready); function ready(playerID){ Froogaloop(playerID).addEvent('play', play(playerID)); Froogaloop(playerID).addEvent('seek', seek); Froogaloop(playerID).api('play'); } function play(playerID){ alert(playerID + " is playing"); } function seek() { alert('Seeking'); } |
This will add a READY event for the player, which allows you to handle other stuff within that function from that point on. Like making the video responsive using fitVid for example :)
Its important that you reference the playerID in the actual iframe source or the ready function will never fire !