>
@@ -228,15 +232,25 @@
Sort By:
-
- > >Date
-
- > >Query
- >
- >Impressions
- >Clicks
- >Avg Position
- >Click Through Rate
+
+ > >Date
+
+
+ > >Query
+
+
+ > >Page
+
+
+ > >
+
+
+ > >Pages
+
+ >Impressions
+ >Clicks
+ >Avg Position
+ >Click Through Rate
diff --git a/organic-search-analytics/js/report.js b/organic-search-analytics/js/report.js
index 02cc90c..6c05400 100644
--- a/organic-search-analytics/js/report.js
+++ b/organic-search-analytics/js/report.js
@@ -37,33 +37,42 @@ function ajaxScript(catId, script, domain, date, callback) {
* Hides granularity when date is not the group by method
* Displays the appropriate sortBy features
*/
+var groupBySortSettings = {
+ groupByDate: {
+ defaultSortBy: "sortByDate",
+ disable: ["sortByQuery","sortByPage"],
+ hideGranularity: false
+ },
+ groupByQuery: {
+ defaultSortBy: "sortByQuery",
+ disable: ["sortByDate","sortByQueries","sortByPage"],
+ hideGranularity: true
+ },
+ groupByPage: {
+ defaultSortBy: "sortByPage",
+ disable: ["sortByDate","sortByQuery","sortByPages"],
+ hideGranularity: true
+ }
+};
jQuery("#report-custom input:radio[name=groupBy]").change(function(e){
- if( e.target.id == "groupByQuery" ) {
- jQuery( "#paramGroup_granularity" ).hide();
-
- var checked_status = jQuery( "#sortByDate" ).prop("checked");
-
- jQuery( "#sortByDate" ).parent("span").hide();
- jQuery( "#sortByDate" ).attr("disabled",true).prop("checked",false);
-
- jQuery( "#sortByQuery" ).parent("span").show();
- jQuery( "#sortByQuery" ).attr("disabled",false);
- if( checked_status ) {
- jQuery( "#sortByQuery" ).prop("checked",true);
- }
- } else {
+ // Toggle granularity
+ if( !groupBySortSettings[e.target.id]['hideGranularity'] ) {
jQuery( "#paramGroup_granularity" ).show();
+ } else {
+ jQuery( "#paramGroup_granularity" ).hide();
+ }
- var checked_status = jQuery( "#sortByQuery" ).prop("checked");
-
- jQuery( "#sortByQuery" ).parent("span").hide();
- jQuery( "#sortByQuery" ).attr("disabled",true).prop("checked",false);
+ // Disable non-applicable sort by options
+ jQuery("#paramGroup_sortBy .sortByOption").show();
+ jQuery("input[name=sortBy]").attr("disabled",false);
+ for( disableOption in groupBySortSettings[e.target.id]['disable'] ) {
+ jQuery("#"+groupBySortSettings[e.target.id]['disable'][disableOption]).parent("span.sortByOption").hide();
+ jQuery("#"+groupBySortSettings[e.target.id]['disable'][disableOption]).attr("disabled",true).prop("checked",false);
+ }
- jQuery( "#sortByDate" ).parent("span").show();
- jQuery( "#sortByDate" ).attr("disabled",false);
- if( checked_status ) {
- jQuery( "#sortByDate" ).prop("checked",true);
- }
+ // Set default option if an option is not set
+ if( !jQuery('input[name=sortBy]').is(':checked') || jQuery("#"+jQuery('input[name=sortBy]:checked').attr("id")).attr("disabled") == "disabled" ) {
+ jQuery( "#"+groupBySortSettings[e.target.id]["defaultSortBy"] ).prop("checked",true);
}
});
diff --git a/organic-search-analytics/log/.gitignore b/organic-search-analytics/log/.gitignore
new file mode 100644
index 0000000..e7a210e
--- /dev/null
+++ b/organic-search-analytics/log/.gitignore
@@ -0,0 +1,3 @@
+*
+*/
+!.gitignore
\ No newline at end of file
diff --git a/organic-search-analytics/report.php b/organic-search-analytics/report.php
index 365c7d2..1f7c564 100644
--- a/organic-search-analytics/report.php
+++ b/organic-search-analytics/report.php
@@ -22,9 +22,11 @@
getReportQueryAndHeading( $reportParams );
$groupBy = $reportDetails['groupBy'];
+ $groupByAlias = $reportDetails['groupByAlias'];
}
?>
@@ -37,8 +39,14 @@
-
+
+
Report Parameters
+
", $reportDetails['pageHeadingItems'] ); ?>
+
+
0 ) {
/* Put MySQL Results into an array */
- $totals = array( 'rows' => 0, 'queries' => 0, 'impressions' => 0, 'clicks' => 0, 'avg_position' => 0, 'avg_ctr' => 0 );
+ $totals = array( 'rows' => 0, 'queries' => 0, 'pages' => 0, 'impressions' => 0, 'clicks' => 0, 'avg_position' => 0, 'avg_ctr' => 0 );
$rows = array();
for( $r=0; $r < count($outputTable); $r++ ) {
- $rows[ $outputTable[$r][$groupBy] ] = array( "queries" => $outputTable[$r]["queries"], "impressions" => $outputTable[$r]["impressions"], "clicks" => $outputTable[$r]["clicks"], "avg_position" => $outputTable[$r]["avg_position"] );
+ $rows[ $outputTable[$r][$groupBy] ] = array( "queries" => $outputTable[$r]["queries"], "pages" => $outputTable[$r]["pages"], "impressions" => $outputTable[$r]["impressions"], "clicks" => $outputTable[$r]["clicks"], "avg_position" => $outputTable[$r]["avg_position"] );
/* Add to totals */
$totals['queries'] += $outputTable[$r]["queries"];
+ $totals['pages'] += $outputTable[$r]["pages"];
$totals['impressions'] += $outputTable[$r]["impressions"];
$totals['clicks'] += $outputTable[$r]["clicks"];
$totals['avg_position'] += $outputTable[$r]["avg_position"];
}
+
/* Calculate averages */
$totals['avg_position'] = number_format( $totals['avg_position'] / count($outputTable), 2 );
$totals['avg_ctr'] = number_format( ( $totals["clicks"] / $totals["impressions"] ) * 100, 2 )."%";
+
/* Format numbers */
+ /*
+ TODO: The totals really should be a separate query for more accurate/useful data.
+ i.e. On a Date report with Year granularity, you might get 50 queries from year 1 and 47 from year 2. These get added together to be 97. But this doesn't account for any overlap in the two years. There may really only be 52 unique queries as an example.
+ */
$totals['rows'] = number_format( count($outputTable), 0 );
$totals['queries'] = number_format( $totals['queries'], 0 );
+ $totals['pages'] = number_format( $totals['pages'], 0 );
$totals['impressions'] = number_format( $totals['impressions'], 0 );
$totals['clicks'] = number_format( $totals['clicks'], 0 );
/* Build an array for chart data */
- $jqData = array( $groupBy => array(), "impressions" => array(), "clicks" => array(), "ctr" => array(), "avg_position" => array() );
+ $jqData = array( $groupByAlias => array(), "impressions" => array(), "clicks" => array(), "ctr" => array(), "avg_position" => array() );
foreach ( $rows as $index => $values ) {
- $jqData[$groupBy][] = $index;
+ if( $groupByAlias == "page" ) {
+ $indexDomain = substr( $index, 0, strlen( $reportParams['domain'] ) );
+ if( strlen( $index ) > strlen( $indexDomain ) && $indexDomain == $reportParams['domain'] ) {
+ $jqData[$groupByAlias][] = substr( $index, strlen( $reportParams['domain'] ) );
+ }
+ } else {
+ $jqData[$groupByAlias][] = $index;
+ }
+
$jqData['impressions'][] = $values["impressions"];
$jqData['clicks'][] = $values["clicks"];
$jqData['ctr'][] = ( $values["clicks"] / $values["impressions"] ) * 100;
$jqData['avg_position'][] = $values["avg_position"];
}
- $num = count( $jqData[$groupBy] );
+ $num = count( $jqData[$groupByAlias] );
$posString = "";
+ $xAxis = "";
$posMax = 0;
for( $c=0; $c<$num; $c++ ) {
if( $c != 0 ) {
$posString .= ",";
+ $xAxis .= ",";
}
- $posString .= "['".addslashes($jqData[$groupBy][$c])."',".$jqData['avg_position'][$c]."]";
+ $posString .= "['".addslashes($jqData[$groupByAlias][$c])."',".$jqData['avg_position'][$c]."]";
if( $jqData['avg_position'][$c] > $posMax ) { $posMax = $jqData['avg_position'][$c]; }
+ $xAxis .= "['".addslashes($jqData[$groupByAlias][$c])."','".addslashes($jqData[$groupByAlias][$c])."']";
}
?>
@@ -152,7 +201,7 @@
+
-
+ array(),
+ "query" => array("queries"),
+ "page" => array("pages")
+ );
+ ?>
$values ) { ?>
-
+
+
$values ) { ?>
+
+ array( "week", "month", "year" ) ); ?>
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Pages
+
+
+
+
+
+
Impressions
+
+
Clicks
+
+
Avg Position
+
+
CTR
+
+
$values ) { ?>
+
+
-
-
+
+ ';
+ }
+ $indexDomain = substr( $index, 0, strlen( $reportParams['domain'] ) );
+ if( strlen( $index ) > strlen( $indexDomain ) && $indexDomain == $reportParams['domain'] ) {
+ echo substr( $index, strlen( $reportParams['domain'] ) );
+ } else {
+ echo ( strlen( $index ) > 0 ? $index : '( not set ) ' );
+ }
+
+ if( $url ) {
+ echo ' ';
+ echo '';
+ }
+ ?>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/organic-search-analytics/settings-configure.php b/organic-search-analytics/settings-configure.php
index 618d3b0..e0208d5 100644
--- a/organic-search-analytics/settings-configure.php
+++ b/organic-search-analytics/settings-configure.php
@@ -19,6 +19,8 @@
$writeToConfigFile .= $t.$t."const OAUTH_CREDENTIALS_PRIVATE_KEY_FILE_NAME = '".$_POST['OAUTH_CREDENTIALS_PRIVATE_KEY_FILE_NAME']."';".$nl;
$writeToConfigFile .= "".$nl;
$writeToConfigFile .= $t.$t."const CREDENTIALS_BING_API_KEY = '".$_POST['CREDENTIALS_BING_API_KEY']."';".$nl;
+ $writeToConfigFile .= "".$nl;
+ $writeToConfigFile .= $t.$t."const DEBUG_LOGGER = ".( isset( $_POST['DEBUG_LOGGER'] ) ? 1 : 0 ).";".$nl;
$writeToConfigFile .= $t."}".$nl;
$writeToConfigFile .= "?>";
@@ -54,6 +56,7 @@
$credentials_bing_api_key = config::CREDENTIALS_BING_API_KEY;
+ $debug_logger = ( defined( 'config::DEBUG_LOGGER' ) ? config::DEBUG_LOGGER : Core::DISABLED );
} else {
$db_connection_host = $db_connection_user = $db_connection_password = $db_connection_database = $oauth_credentials_private_key_file_name = $oauth_credentials_email = $credentials_bing_api_key = "";
}
@@ -103,9 +106,17 @@
+
+ Debug Logging
+
+
+ Enable Debug Logger
+ ">
+
+
-
+
diff --git a/organic-search-analytics/settings.php b/organic-search-analytics/settings.php
index 83e06c3..a16859a 100644
--- a/organic-search-analytics/settings.php
+++ b/organic-search-analytics/settings.php
@@ -10,12 +10,13 @@
$siteSettings = array();
$siteSettings['Google'] = $mysql->getSettings("sites_google");
$siteSettings['Bing'] = $mysql->getSettings("sites_bing");
-
+ $siteSettings['Settings'] = $mysql->getSettings("settings");
+
/* Get list of sites */
$wmtSites = array();
$wmtSites['Google'] = $dataCapture->getSitesGoogleSearchConsole();
$wmtSites['Bing'] = $dataCapture->getSitesBingWebmaster();
-
+
/* Get combined sites */
foreach( $wmtSites as $searchEngine => $sitesData ) {
foreach( $sitesData as $key => $data ) {
@@ -37,12 +38,55 @@
}
}
+ /* Define settings for the page */
+ $settingsSetup = array(
+ "google" => array(
+ "description" => "Customize what infomration is captured from Google",
+ "label" => "Google",
+ "products" => array(
+ "search_console" => array(
+ "description" => "Select which dimensions you'd like to capture.NOTE : Adding more dimensions could limit the accuracy of the data you obtain. The Google API provides up to 5,000 results per request. To illustrate this example, if you select Queries only lets say there were 10 queries for that day. If you then add Country and each query was returned in 5 countries each, you now are receiving 50 results (10 queries X 5 countries). Adding Device Type , assuming each query in each country was performed on each Device Type the number of results would grow to 150 results. You can see how as you add additional dimensions the number of results can grow quickly. Depending on frequently your site shows in the SERPs this may or may not impact your ability to capture all of the avaialbe data. ",
+ "label" => "Search Console",
+ "section" => array(
+ "dimensions" => array(
+ "description" => " section description",
+ "heading" => "Dimensions",
+ "heading_options" => "Enable/Disable",
+ "options" => array(
+ "query" => array(
+ "label" => "Queries",
+ "type" => "checkbox",
+ "note" => ""
+ ),
+ "page" => array(
+ "label" => "Page (URL)",
+ "type" => "checkbox",
+ "note" => ""
+ ),
+ "device" => array(
+ "label" => "Device Type",
+ "type" => "checkbox",
+ "note" => "Will return Desktop , Mobile , or Tablet "
+ ),
+ "country" => array(
+ "label" => "Country",
+ "type" => "checkbox",
+ "note" => ""
+ )
+ )
+ )
+ )
+ )
+ )
+ )
+ );
+
/* Update settings table */
if( isset( $_POST['save_settings'] ) ) {
foreach( $sitesList as $site => $data ) {
// Set to checked
$siteToAdd = addslashes( $site );
-
+
foreach( $data['availableTo'] as $searchEngine ) {
if( in_array( $searchEngine, $data['enabled'] ) && isset( $_POST['site_settings'][$site][$searchEngine] ) ) {
//do nothing
@@ -63,6 +107,35 @@
}
}
}
+
+ /* Loop through settings and update database where necessary */
+ foreach( $settingsSetup as $searchEngine => $settingsGroup ) {
+ foreach( $settingsGroup['products'] as $productName => $productGroup ) {
+ foreach( $productGroup['section'] as $sectionName => $sectionGroup ) {
+ foreach( $sectionGroup['options'] as $optionName => $optionGroup ) {
+ $value = $searchEngine."_".$productName."_".$sectionName."_".$optionName;
+ switch( $optionGroup['type'] ) {
+ case "checkbox":
+ if( isset( $_POST['settings'][$searchEngine][$productName][$sectionName][$optionName] ) ) { $data = "On"; } else { $data = "Off"; }
+ break;
+ default:
+ $data = $_POST['settings'][$searchEngine][$productName][$sectionName][$optionName];
+ }
+
+ // Update the database
+ if( !isset( $siteSettings['Settings'][$value] ) ) {
+ $response = $mysql->qryDBinsert( $mysql::DB_TABLE_SETTINGS, "NULL, 'settings', '$value', '$data'" );
+ } elseif ( isset( $siteSettings['Settings'][$value] ) && $siteSettings['Settings'][$value] != $data ) {
+ $response = $mysql->qryDBupdate( $mysql::DB_TABLE_SETTINGS, array( 'type' => 'settings', 'value' => $value ), array( 'data' => $data ) );
+ }
+
+ // Update settings loaded ot page
+ $siteSettings['Settings'][$value] = $data;
+ }
+ }
+ }
+ }
+
$alert = array("type"=>"success", "message"=>"Settings Succesfully Saved");
}
}
@@ -85,12 +158,20 @@
Site Setup
- Select the sites and Search Engine to capture data from.
+
+
Select the sites and Search Engine to capture data from.
+
Not seeing the sites you expect?
Google Search Console
- Ensure that you have enabled the Google Search Console API and added your Google API Service Account email address as a user to each of your sites in Google Search Console.Instruction on how to configure Google Search Analytics for API Access
+
+
+
Bing Webmaster Tools
- Ensure that you have configured your site with Bing Wembaster Tools and that the API key set in the configuration matches that of the API key found in Bing Webmaster Tools .
+
+
+ $settingsGroup ) {?>
+
+ 0 ) { ?>
+ $productGroup ) { ?>
+
+
Options
+ 0 ) { ?>
+ $sectionGroup ) { ?>
+
+ $optionGroup ) { ?>
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/organic-search-analytics/upgrade.php b/organic-search-analytics/upgrade.php
index d6d1c04..1d6e648 100644
--- a/organic-search-analytics/upgrade.php
+++ b/organic-search-analytics/upgrade.php
@@ -66,6 +66,77 @@
$alert = array("type"=>"success", "message"=>"Upgrade performed succesfully.");
break;
+ case "2_x_x_to_2_5_0":
+ /* Include resources */
+ include_once( 'inc/code/core.php' ); //Core functions
+ include_once( 'inc/code/mysql.php' ); //Database Connection
+ $core = new Core(); //Load core
+ $mysql = new MySQL(); //Load MySQL
+ $GLOBALS['db'] = $core->mysql_connect_db(); // Connect to DB
+
+ $errors = array();
+
+ /* Table: search_analytics */
+ $query = "ALTER TABLE `search_analytics`".
+ " ADD `page` VARCHAR(500) NULL DEFAULT NULL AFTER `query`,".
+ " CHANGE COLUMN `device_type` `device_type` VARCHAR(24) NULL DEFAULT NULL,".
+ " CHANGE COLUMN `country` `country` VARCHAR(10) NULL DEFAULT NULL,".
+ " CHANGE COLUMN `query` `query` VARCHAR(500) NULL DEFAULT NULL,".
+ " CHANGE COLUMN `avg_position` `avg_position` FLOAT NULL DEFAULT NULL,".
+ " CHANGE COLUMN `avg_position_click` `avg_position_click` FLOAT NULL DEFAULT NULL,".
+ " CONVERT TO CHARACTER SET `utf8` COLLATE `utf8_unicode_ci`"
+ ;
+ $result = $mysql->query( $query );
+ if( !$result ) {
+ $errors[] = $mysql->error;
+ }
+
+ /* Table: search_analytics */
+ /* Action: Prepopulate settings */
+ $query = "INSERT INTO `settings`".
+ " (type, value, data)".
+ "VALUES".
+ " ('settings', 'google_search_console_dimensions_query', 'On'),".
+ " ('settings', 'google_search_console_dimensions_page', 'Off'),".
+ " ('settings', 'google_search_console_dimensions_device', 'On'),".
+ " ('settings', 'google_search_console_dimensions_country', 'On')"
+ ;
+ $result = $mysql->query( $query );
+ if( !$result ) {
+ $errors[] = $mysql->error;
+ }
+
+ /* Table: report_saved */
+ $query = "ALTER TABLE `report_saved` CONVERT TO CHARACTER SET `utf8` COLLATE `utf8_unicode_ci`";
+ $result = $mysql->query( $query );
+ if( !$result ) {
+ $errors[] = $mysql->error;
+ }
+
+ /* Table: report_saved_categories */
+ $query = "ALTER TABLE `report_saved_categories` CONVERT TO CHARACTER SET `utf8` COLLATE `utf8_unicode_ci`";
+ $result = $mysql->query( $query );
+ if( !$result ) {
+ $errors[] = $mysql->error;
+ }
+
+ /* Table: settings */
+ $query = "ALTER TABLE `settings` ENGINE=`INNODB`, CONVERT TO CHARACTER SET `utf8` COLLATE `utf8_unicode_ci`";
+ $result = $mysql->query( $query );
+ if( !$result ) {
+ $errors[] = $mysql->error;
+ }
+
+ if( !count( $errors ) ) {
+ $alert = array("type"=>"success", "message"=>"Upgrade performed succesfully.");
+ } else {
+ $errorString = "There were errors in the upgrade process. ";
+ $errorString .= implode(" ", $errors );
+ $alert = array("type"=>"error", "message"=>$errorString);
+ }
+
+ $alert = array("type"=>"success", "message"=>"Upgrade performed succesfully. Go to the Settings Configuration page and click the Save button.");
+ break;
}
}
?>
@@ -76,11 +147,40 @@
Certain versions require special consideration when upgrading. This page will take care of technical changes that need to be made.
NOTE : If upgrading through multiple versions, it's advised to run all of the updates in order.
+
+ Version 2.x.x to 2.5.0
+
+ Several database changes:
+
+ Adds column page to the search_analytics table.
+ Updates column country to default to NULL.
+ Updates column query to allow NULL and default to NULL.
+ Updates column device_type to allow NULL and default to NULL.
+ Updates column avarage_position setting default to NULL and change type from int(11) to float.
+ Updates column avarage_position_click changing type from int(11) to float.
+ Change the default character set to utf8 for all tables
+ Change the engine from MyISAM to InnoDB on the settings table.
+
+ Added debug logging functionality (only added to Data Capture processes at this time)
+
+ NOTE: Manual Upgrade Step is Required!
+ Go to the Settings Configuration page and click the Save button. This updates your config file to add the Debug Logger configuration. You do NOT need to enable it (and it is wise not to unless you need to do debugging).
+
+ Run Update for Version 2.x.x to 2.5.0
+
+
+
+ Version 2.x.x to 2.4.0
+
+
Version 2.1.0 and below to 2.2.0
@@ -88,14 +188,7 @@
Adds the CREDENTIALS_BING_API_KEY constant to the config/config.php file to allow for setting the Bing Webmaster Tools API connection.
Updates the Click Through Rate data type in the search_analytics table to correct data inaccuracies.
- Run Update for Version 1.x to 2.0.0
-
-
-
- Version 2.x.x to 2.4.0
-
diff --git a/organic-search-analytics/version.txt b/organic-search-analytics/version.txt
index 35cee72..437459c 100644
--- a/organic-search-analytics/version.txt
+++ b/organic-search-analytics/version.txt
@@ -1 +1 @@
-2.4.3
+2.5.0