diff --git a/plugins/CoreHome/angularjs/history/history.service.js b/plugins/CoreHome/angularjs/history/history.service.js
index 555afba6b6cd96fe04d166aad7da3eec19611e7f..828217a5fa0b813e3fb9105adbe1027957a33b0b 100644
--- a/plugins/CoreHome/angularjs/history/history.service.js
+++ b/plugins/CoreHome/angularjs/history/history.service.js
@@ -25,6 +25,10 @@
         return service;
 
         function init() {
+            if ($location.path() != '/') {
+                changePathToSearch();
+            }
+
             $rootScope.$on('$locationChangeSuccess', function () {
                 loadCurrentPage();
             });
@@ -32,9 +36,43 @@
             loadCurrentPage();
         }
 
+        // currently, the AJAX content URL is stored in $location.search(), but before it was stored in $location.path().
+        // this function makes sure URLs like http://piwik.net/?...#/module=Whatever&action=whatever still work.
+        function changePathToSearch() {
+            var path = $location.path();
+            if (!path
+                || path == '/'
+            ) {
+                return;
+            }
+
+            var searchParams = broadcast.getValuesFromUrl('?' + path.substring(1));
+            // NOTE: we don't need to decode the parameters since $location.path() will decode the string itself
+
+            $location.search(searchParams);
+            $location.path('');
+        }
+
         function loadCurrentPage() {
+            var searchObject = $location.search(),
+                searchString = [];
+            for (var name in searchObject) {
+                if (!searchObject.hasOwnProperty(name)) {
+                    continue;
+                }
+
+                // if more than one query parameter of the same name is supplied, angular will return all of them as
+                // an array. we only want to use the last one, though.
+                if (searchObject[name] instanceof Array) {
+                    searchObject[name] = searchObject[name][searchObject[name].length - 1];
+                }
+
+                searchString.push(name + '=' + encodeURIComponent(searchObject[name]));
+            }
+            searchString = searchString.join('&');
+
             // the location hash will have a / prefix, which broadcast.pageload doesn't want
-            broadcast.pageload($location.path().substring(1));
+            broadcast.pageload(searchString);
         }
 
         function load(hash) {
@@ -47,7 +85,15 @@
                 }
             }
 
-            $location.path(hash);
+            if (hash) {
+                $location.search(hash);
+            } else {
+                // NOTE: this works around a bug in angularjs. when unsetting the hash (ie, removing in the URL),
+                // angular will enter an infinite loop of digests. this is because $locationWatch will trigger
+                // $locationChangeStart if $browser.url() != $location.absUrl(), and $browser.url() will contain
+                // the '#' character and $location.absUrl() will not. so the watch continues to trigger the event.
+                $location.search('_=');
+            }
 
             setTimeout(function () { $rootScope.$apply(); }, 1);
         }
diff --git a/plugins/CoreHome/javascripts/broadcast.js b/plugins/CoreHome/javascripts/broadcast.js
index 4b6ca7e9978761188937eff5bbeab0f0d3c9b305..706a8e59d59f856ccd1acb4737f17bb3a483bee3 100644
--- a/plugins/CoreHome/javascripts/broadcast.js
+++ b/plugins/CoreHome/javascripts/broadcast.js
@@ -215,7 +215,7 @@ var broadcast = {
         }
 
         if (disableHistory) {
-            var newLocation = window.location.href.split('#')[0] + '#' + currentHashStr;
+            var newLocation = window.location.href.split('#')[0] + '#?' + currentHashStr;
             // window.location.replace changes the current url without pushing it on the browser's history stack
             window.location.replace(newLocation);
         }
diff --git a/plugins/Overlay/javascripts/Overlay_Helper.js b/plugins/Overlay/javascripts/Overlay_Helper.js
index 13feff40827c8a8b96e85e1248499bb183efb208..e0681e7b454c4e48472936e3418f22bf3ec01b43 100644
--- a/plugins/Overlay/javascripts/Overlay_Helper.js
+++ b/plugins/Overlay/javascripts/Overlay_Helper.js
@@ -23,7 +23,7 @@ var Overlay_Helper = {
     getOverlayLink: function (idSite, period, date, link) {
         var url = 'index.php?module=Overlay&period=' + encodeURIComponent(period) + '&date=' + encodeURIComponent(date) + '&idSite=' + encodeURIComponent(idSite);
         if (link) {
-            url += '#l=' + Overlay_Helper.encodeFrameUrl(link);
+            url += '#?l=' + Overlay_Helper.encodeFrameUrl(link);
         }
         return url;
     }
diff --git a/plugins/Overlay/javascripts/Piwik_Overlay.js b/plugins/Overlay/javascripts/Piwik_Overlay.js
index b7f38a89b4532ae93ac55fdcb3c0dfb3f57d1f3d..4c780808064bf8e67d5e0e7a3f30a0eb4035cc93 100644
--- a/plugins/Overlay/javascripts/Piwik_Overlay.js
+++ b/plugins/Overlay/javascripts/Piwik_Overlay.js
@@ -111,9 +111,19 @@ var Piwik_Overlay = (function () {
         $fullScreenLink.show();
     }
 
+    function getOverlayLocationFromHash(urlHash) {
+        var location = broadcast.getParamValue('l', urlHash);
+
+        // angular will encode the value again since it is added as the fragment path, not the fragment query parameter,
+        // so we have to decode it again after getParamValue
+        location = decodeURIComponent(location);
+
+        return location;
+    }
+
     /** $.history callback for hash change */
     function hashChangeCallback(urlHash) {
-        var location = broadcast.getParamValue('l', urlHash);
+        var location = getOverlayLocationFromHash(urlHash);
         location = Overlay_Helper.decodeFrameUrl(location);
 
         if (!updateComesFromInsideFrame) {
@@ -243,7 +253,7 @@ var Piwik_Overlay = (function () {
             var locationParts = location.href.split('#');
             var currentLocation = '';
             if (locationParts.length > 1) {
-                currentLocation = broadcast.getParamValue('l', locationParts[1]);
+                currentLocation = getOverlayLocationFromHash(locationParts[1]);
             }
 
             var newLocation = Overlay_Helper.encodeFrameUrl(currentUrl);
diff --git a/tests/UI/specs/UIIntegration_spec.js b/tests/UI/specs/UIIntegration_spec.js
index 97e3afad93e451d970ab88e1bbc7200d19da63bc..1334a9dd19f80a74238fcb63c950f19cda673028 100644
--- a/tests/UI/specs/UIIntegration_spec.js
+++ b/tests/UI/specs/UIIntegration_spec.js
@@ -614,5 +614,28 @@ describe("UIIntegrationTest", function () { // TODO: Rename to Piwik?
         }, done);
     });
 
+    // extra segment tests
+    it('should load the row evolution page correctly when a segment is selected', function (done) {
+        var url = "?module=CoreHome&action=index&idSite=1&period=year&date=2012-01-13#?module=CustomVariables&action=menuGetCustomVariables&idSite=1&period=year&date=2012-01-13";
+        expect.page(url).contains('.ui-dialog > .ui-dialog-content > div.rowevolution:visible', 'segmented_rowevolution', function (page) {
+            page.click('.segmentationTitle');
+            page.click('.segname:contains(From Europe)');
 
+            page.mouseMove('table.dataTable tbody tr:first-child');
+            page.mouseMove('a.actionRowEvolution:visible'); // necessary to get popover to display
+            page.click('a.actionRowEvolution:visible');
+        }, done);
+    });
+
+    it('should load the segmented visitor log correctly when a segment is selected', function (done) {
+        var url = "?module=CoreHome&action=index&idSite=1&period=year&date=2012-01-13#?module=CustomVariables&action=menuGetCustomVariables&idSite=1&period=year&date=2012-01-13";
+        expect.page(url).contains('.ui-dialog > .ui-dialog-content > div.dataTableVizVisitorLog:visible', 'segmented_visitorlog', function (page) {
+            page.click('.segmentationTitle');
+            page.click('.segname:contains(From Europe)');
+
+            page.mouseMove('table.dataTable tbody tr:first-child');
+            page.mouseMove('a.actionSegmentVisitorLog:visible'); // necessary to get popover to display
+            page.click('a.actionSegmentVisitorLog:visible');
+        }, done);
+    });
 });
\ No newline at end of file