Kaynağa Gözat

google analytics

Bachir Soussi Chiadmi 10 yıl önce
ebeveyn
işleme
9b7d1f6199

+ 339 - 0
sites/all/modules/contrib/admin/google_analytics/LICENSE.txt

@@ -0,0 +1,339 @@
+                    GNU GENERAL PUBLIC LICENSE
+                       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                            Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+                    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+                            NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+                     END OF TERMS AND CONDITIONS
+
+            How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License along
+    with this program; if not, write to the Free Software Foundation, Inc.,
+    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) year name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.

+ 79 - 0
sites/all/modules/contrib/admin/google_analytics/README.txt

@@ -0,0 +1,79 @@
+
+Module: Google Analytics
+Author: Alexander Hass <http://drupal.org/user/85918>
+
+
+Description
+===========
+Adds the Google Analytics tracking system to your website.
+
+Requirements
+============
+
+* Google Analytics user account
+
+
+Installation
+============
+Copy the 'googleanalytics' module directory in to your Drupal
+sites/all/modules directory as usual.
+
+
+Usage
+=====
+In the settings page enter your Google Analytics account number.
+
+All pages will now have the required JavaScript added to the
+HTML footer can confirm this by viewing the page source from
+your browser.
+
+New approach to page tracking in 5.x-1.5 and 6.x-1.1
+====================================================
+With 5.x-1.5 and 6.x-1.1 there are new settings on the settings page at
+admin/config/system/googleanalytics. The "Page specific tracking" area now
+comes with an interface that copies Drupal's block visibility settings.
+
+The default is set to "Add to every page except the listed pages". By
+default the following pages are listed for exclusion:
+
+admin
+admin/*
+batch
+node/add*
+node/*/*
+user/*/*
+
+These defaults are changeable by the website administrator or any other
+user with 'administer google analytics' permission.
+
+Like the blocks visibility settings in Drupal core, there is now a
+choice for "Add if the following PHP code returns TRUE." Sample PHP snippets
+that can be used in this textarea can be found on the handbook page
+"Overview-approach to block visibility" at http://drupal.org/node/64135.
+
+Custom dimensions and metrics
+=============================
+One example for custom dimensions tracking is the "User roles" tracking.
+
+1. In the Google Analytics Management Interface you need to setup Dimension #1
+   with name e.g. "User roles". This step is required. Do not miss it, please.
+
+2. Enter the below configuration data into the custom dimensions settings form
+   under admin/config/system/googleanalytics. You can also choose another index,
+   but keep it always in sync with the index used in step #1.
+
+   Index: 1
+   Value: [current-user:role-names]
+
+More details about custom dimensions and metrics can be found in the Google API
+documentation at https://developers.google.com/analytics/devguides/collection/analyticsjs/custom-dims-mets
+
+Advanced Settings
+=================
+You can include additional JavaScript snippets in the custom javascript
+code textarea. These can be found on the official Google Analytics pages
+and a few examples at http://drupal.org/node/248699. Support is not
+provided for any customisations you include.
+
+To speed up page loading you may also cache the Google Analytics "analytics.js"
+file locally.

Dosya farkı çok büyük olduğundan ihmal edildi
+ 23 - 0
sites/all/modules/contrib/admin/google_analytics/googleanalytics.admin.inc


+ 131 - 0
sites/all/modules/contrib/admin/google_analytics/googleanalytics.admin.js

@@ -0,0 +1,131 @@
+(function ($) {
+
+/**
+ * Provide the summary information for the tracking settings vertical tabs.
+ */
+Drupal.behaviors.trackingSettingsSummary = {
+  attach: function (context) {
+    // Make sure this behavior is processed only if drupalSetSummary is defined.
+    if (typeof jQuery.fn.drupalSetSummary == 'undefined') {
+      return;
+    }
+
+    $('fieldset#edit-page-vis-settings', context).drupalSetSummary(function (context) {
+      var $radio = $('input[name="googleanalytics_visibility_pages"]:checked', context);
+      if ($radio.val() == 0) {
+        if (!$('textarea[name="googleanalytics_pages"]', context).val()) {
+          return Drupal.t('Not restricted');
+        }
+        else {
+          return Drupal.t('All pages with exceptions');
+        }
+      }
+      else {
+        return Drupal.t('Restricted to certain pages');
+      }
+    });
+
+    $('fieldset#edit-role-vis-settings', context).drupalSetSummary(function (context) {
+      var vals = [];
+      $('input[type="checkbox"]:checked', context).each(function () {
+        vals.push($.trim($(this).next('label').text()));
+      });
+      if (!vals.length) {
+        return Drupal.t('Not restricted');
+      }
+      else if ($('input[name="googleanalytics_visibility_roles"]:checked', context).val() == 1) {
+        return Drupal.t('Excepted: @roles', {'@roles' : vals.join(', ')});
+      }
+      else {
+        return vals.join(', ');
+      }
+    });
+
+    $('fieldset#edit-user-vis-settings', context).drupalSetSummary(function (context) {
+      var $radio = $('input[name="googleanalytics_custom"]:checked', context);
+      if ($radio.val() == 0) {
+        return Drupal.t('Not customizable');
+      }
+      else if ($radio.val() == 1) {
+        return Drupal.t('On by default with opt out');
+      }
+      else {
+        return Drupal.t('Off by default with opt in');
+      }
+    });
+
+    $('fieldset#edit-linktracking', context).drupalSetSummary(function (context) {
+      var vals = [];
+      if ($('input#edit-googleanalytics-trackoutbound', context).is(':checked')) {
+        vals.push(Drupal.t('Outbound links'));
+      }
+      if ($('input#edit-googleanalytics-trackmailto', context).is(':checked')) {
+        vals.push(Drupal.t('Mailto links'));
+      }
+      if ($('input#edit-googleanalytics-trackfiles', context).is(':checked')) {
+        vals.push(Drupal.t('Downloads'));
+      }
+      if (!vals.length) {
+        return Drupal.t('Not tracked');
+      }
+      return Drupal.t('@items enabled', {'@items' : vals.join(', ')});
+    });
+
+    $('fieldset#edit-messagetracking', context).drupalSetSummary(function (context) {
+      var vals = [];
+      $('input[type="checkbox"]:checked', context).each(function () {
+        vals.push($.trim($(this).next('label').text()));
+      });
+      if (!vals.length) {
+        return Drupal.t('Not tracked');
+      }
+      return Drupal.t('@items enabled', {'@items' : vals.join(', ')});
+    });
+
+    $('fieldset#edit-search-and-advertising', context).drupalSetSummary(function (context) {
+      var vals = [];
+      if ($('input#edit-googleanalytics-site-search', context).is(':checked')) {
+        vals.push(Drupal.t('Site search'));
+      }
+      if ($('input#edit-googleanalytics-trackadsense', context).is(':checked')) {
+        vals.push(Drupal.t('AdSense ads'));
+      }
+      if ($('input#edit-googleanalytics-trackdoubleclick', context).is(':checked')) {
+        vals.push(Drupal.t('Display features'));
+      }
+      if (!vals.length) {
+        return Drupal.t('Not tracked');
+      }
+      return Drupal.t('@items enabled', {'@items' : vals.join(', ')});
+    });
+
+    $('fieldset#edit-domain-tracking', context).drupalSetSummary(function (context) {
+      var $radio = $('input[name="googleanalytics_domain_mode"]:checked', context);
+      if ($radio.val() == 0) {
+        return Drupal.t('A single domain');
+      }
+      else if ($radio.val() == 1) {
+        return Drupal.t('One domain with multiple subdomains');
+      }
+      else {
+        return Drupal.t('Multiple top-level domains');
+      }
+    });
+
+    $('fieldset#edit-privacy', context).drupalSetSummary(function (context) {
+      var vals = [];
+      if ($('input#edit-googleanalytics-tracker-anonymizeip', context).is(':checked')) {
+        vals.push(Drupal.t('Anonymize IP'));
+      }
+      if ($('input#edit-googleanalytics-privacy-donottrack', context).is(':checked')) {
+        vals.push(Drupal.t('Universal web tracking opt-out'));
+      }
+      if (!vals.length) {
+        return Drupal.t('No privacy');
+      }
+      return Drupal.t('@items enabled', {'@items' : vals.join(', ')});
+    });
+  }
+};
+
+})(jQuery);

+ 183 - 0
sites/all/modules/contrib/admin/google_analytics/googleanalytics.debug.js

@@ -0,0 +1,183 @@
+(function ($) {
+
+Drupal.googleanalytics = {};
+
+$(document).ready(function() {
+
+  // Attach mousedown, keyup, touchstart events to document only and catch
+  // clicks on all elements.
+  $(document.body).bind("mousedown keyup touchstart", function(event) {
+    console.group("Running Google Analytics for Drupal.");
+    console.info(event);
+
+    // Catch the closest surrounding link of a clicked element.
+    $(event.target).closest("a,area").each(function() {
+      console.info("Element '%o' has been detected. Link '%s' found.", this, this.href);
+
+      // Is the clicked URL internal?
+      if (Drupal.googleanalytics.isInternal(this.href)) {
+        // Skip 'click' tracking, if custom tracking events are bound.
+        if ($(this).is('.colorbox')) {
+          // Do nothing here. The custom event will handle all tracking.
+          console.info("Click on .colorbox item has been detected.");
+        }
+        // Is download tracking activated and the file extension configured for download tracking?
+        else if (Drupal.settings.googleanalytics.trackDownload && Drupal.googleanalytics.isDownload(this.href)) {
+          // Download link clicked.
+          console.info("Download url '%s' has been found. Tracked download as extension '%s'.", Drupal.googleanalytics.getPageUrl(this.href), Drupal.googleanalytics.getDownloadExtension(this.href).toUpperCase());
+          ga("send", "event", "Downloads", Drupal.googleanalytics.getDownloadExtension(this.href).toUpperCase(), Drupal.googleanalytics.getPageUrl(this.href));
+        }
+        else if (Drupal.googleanalytics.isInternalSpecial(this.href)) {
+          // Keep the internal URL for Google Analytics website overlay intact.
+          console.info("Click on internal special link '%s' has been tracked.", Drupal.googleanalytics.getPageUrl(this.href));
+          ga("send", "pageview", { "page": Drupal.googleanalytics.getPageUrl(this.href) });
+        }
+        else {
+          // e.g. anchor in same page or other internal page link
+          console.info("Click on internal link '%s' detected, but not tracked by click.", this.href);
+        }
+      }
+      else {
+        if (Drupal.settings.googleanalytics.trackMailto && $(this).is("a[href^='mailto:'],area[href^='mailto:']")) {
+          // Mailto link clicked.
+          console.info("Click on e-mail '%s' has been tracked.", this.href.substring(7));
+          ga("send", "event", "Mails", "Click", this.href.substring(7));
+        }
+        else if (Drupal.settings.googleanalytics.trackOutbound && this.href.match(/^\w+:\/\//i)) {
+          if (Drupal.settings.googleanalytics.trackDomainMode != 2 || (Drupal.settings.googleanalytics.trackDomainMode == 2 && !Drupal.googleanalytics.isCrossDomain(this.hostname, Drupal.settings.googleanalytics.trackCrossDomains))) {
+            // External link clicked / No top-level cross domain clicked.
+            console.info("Outbound link '%s' has been tracked.", this.href);
+            ga("send", "event", "Outbound links", "Click", this.href);
+          }
+          else {
+            console.info("Internal link '%s' clicked, not tracked.", this.href);
+          }
+        }
+      }
+    });
+
+    console.groupEnd();
+  });
+
+  // Track hash changes as unique pageviews, if this option has been enabled.
+  if (Drupal.settings.googleanalytics.trackUrlFragments) {
+    window.onhashchange = function() {
+      console.info("Track URL '%s' as pageview. Hash '%s' has changed.", location.pathname + location.search + location.hash, location.hash);
+      ga('send', 'pageview', location.pathname + location.search + location.hash);
+    }
+  }
+
+  // Colorbox: This event triggers when the transition has completed and the
+  // newly loaded content has been revealed.
+  $(document).bind("cbox_complete", function () {
+    var href = $.colorbox.element().attr("href");
+    if (href) {
+      console.info("Colorbox transition to url '%s' has been tracked.", Drupal.googleanalytics.getPageUrl(href));
+      ga("send", "pageview", { "page": Drupal.googleanalytics.getPageUrl(href) });
+    }
+  });
+
+});
+
+/**
+ * Check whether the hostname is part of the cross domains or not.
+ *
+ * @param string hostname
+ *   The hostname of the clicked URL.
+ * @param array crossDomains
+ *   All cross domain hostnames as JS array.
+ *
+ * @return boolean
+ */
+Drupal.googleanalytics.isCrossDomain = function (hostname, crossDomains) {
+  /**
+   * jQuery < 1.6.3 bug: $.inArray crushes IE6 and Chrome if second argument is
+   * `null` or `undefined`, http://bugs.jquery.com/ticket/10076,
+   * https://github.com/jquery/jquery/commit/a839af034db2bd934e4d4fa6758a3fed8de74174
+   *
+   * @todo: Remove/Refactor in D8
+   */
+  if (!crossDomains) {
+    return false;
+  }
+  else {
+    return $.inArray(hostname, crossDomains) > -1 ? true : false;
+  }
+};
+
+/**
+ * Check whether this is a download URL or not.
+ *
+ * @param string url
+ *   The web url to check.
+ *
+ * @return boolean
+ */
+Drupal.googleanalytics.isDownload = function (url) {
+  var isDownload = new RegExp("\\.(" + Drupal.settings.googleanalytics.trackDownloadExtensions + ")([\?#].*)?$", "i");
+  return isDownload.test(url);
+};
+
+/**
+ * Check whether this is an absolute internal URL or not.
+ *
+ * @param string url
+ *   The web url to check.
+ *
+ * @return boolean
+ */
+Drupal.googleanalytics.isInternal = function (url) {
+  var isInternal = new RegExp("^(https?):\/\/" + window.location.host, "i");
+  return isInternal.test(url);
+};
+
+/**
+ * Check whether this is a special URL or not.
+ *
+ * URL types:
+ *  - gotwo.module /go/* links.
+ *
+ * @param string url
+ *   The web url to check.
+ *
+ * @return boolean
+ */
+Drupal.googleanalytics.isInternalSpecial = function (url) {
+  var isInternalSpecial = new RegExp("(\/go\/.*)$", "i");
+  return isInternalSpecial.test(url);
+};
+
+/**
+ * Extract the relative internal URL from an absolute internal URL.
+ *
+ * Examples:
+ * - http://mydomain.com/node/1 -> /node/1
+ * - http://example.com/foo/bar -> http://example.com/foo/bar
+ *
+ * @param string url
+ *   The web url to check.
+ *
+ * @return string
+ *   Internal website URL
+ */
+Drupal.googleanalytics.getPageUrl = function (url) {
+  var extractInternalUrl = new RegExp("^(https?):\/\/" + window.location.host, "i");
+  return url.replace(extractInternalUrl, '');
+};
+
+/**
+ * Extract the download file extension from the URL.
+ *
+ * @param string url
+ *   The web url to check.
+ *
+ * @return string
+ *   The file extension of the passed url. e.g. "zip", "txt"
+ */
+Drupal.googleanalytics.getDownloadExtension = function (url) {
+  var extractDownloadextension = new RegExp("\\.(" + Drupal.settings.googleanalytics.trackDownloadExtensions + ")([\?#].*)?$", "i");
+  var extension = extractDownloadextension.exec(url);
+  return (extension === null) ? '' : extension[1];
+};
+
+})(jQuery);

+ 13 - 0
sites/all/modules/contrib/admin/google_analytics/googleanalytics.info

@@ -0,0 +1,13 @@
+name = Google Analytics
+description = Allows your site to be tracked by Google Analytics by adding a Javascript tracking code to every page.
+core = 7.x
+package = Statistics
+configure = admin/config/system/googleanalytics
+files[] = googleanalytics.test
+test_dependencies[] = token
+; Information added by Drupal.org packaging script on 2014-11-29
+version = "7.x-2.1"
+core = "7.x"
+project = "google_analytics"
+datestamp = "1417276982"
+

Dosya farkı çok büyük olduğundan ihmal edildi
+ 360 - 0
sites/all/modules/contrib/admin/google_analytics/googleanalytics.install


+ 165 - 0
sites/all/modules/contrib/admin/google_analytics/googleanalytics.js

@@ -0,0 +1,165 @@
+(function ($) {
+
+Drupal.googleanalytics = {};
+
+$(document).ready(function() {
+
+  // Attach mousedown, keyup, touchstart events to document only and catch
+  // clicks on all elements.
+  $(document.body).bind("mousedown keyup touchstart", function(event) {
+
+    // Catch the closest surrounding link of a clicked element.
+    $(event.target).closest("a,area").each(function() {
+
+      // Is the clicked URL internal?
+      if (Drupal.googleanalytics.isInternal(this.href)) {
+        // Skip 'click' tracking, if custom tracking events are bound.
+        if ($(this).is('.colorbox')) {
+          // Do nothing here. The custom event will handle all tracking.
+          //console.info("Click on .colorbox item has been detected.");
+        }
+        // Is download tracking activated and the file extension configured for download tracking?
+        else if (Drupal.settings.googleanalytics.trackDownload && Drupal.googleanalytics.isDownload(this.href)) {
+          // Download link clicked.
+          ga("send", "event", "Downloads", Drupal.googleanalytics.getDownloadExtension(this.href).toUpperCase(), Drupal.googleanalytics.getPageUrl(this.href));
+        }
+        else if (Drupal.googleanalytics.isInternalSpecial(this.href)) {
+          // Keep the internal URL for Google Analytics website overlay intact.
+          ga("send", "pageview", { "page": Drupal.googleanalytics.getPageUrl(this.href) });
+        }
+      }
+      else {
+        if (Drupal.settings.googleanalytics.trackMailto && $(this).is("a[href^='mailto:'],area[href^='mailto:']")) {
+          // Mailto link clicked.
+          ga("send", "event", "Mails", "Click", this.href.substring(7));
+        }
+        else if (Drupal.settings.googleanalytics.trackOutbound && this.href.match(/^\w+:\/\//i)) {
+          if (Drupal.settings.googleanalytics.trackDomainMode != 2 || (Drupal.settings.googleanalytics.trackDomainMode == 2 && !Drupal.googleanalytics.isCrossDomain(this.hostname, Drupal.settings.googleanalytics.trackCrossDomains))) {
+            // External link clicked / No top-level cross domain clicked.
+            ga("send", "event", "Outbound links", "Click", this.href);
+          }
+        }
+      }
+    });
+  });
+
+  // Track hash changes as unique pageviews, if this option has been enabled.
+  if (Drupal.settings.googleanalytics.trackUrlFragments) {
+    window.onhashchange = function() {
+      ga('send', 'pageview', location.pathname + location.search + location.hash);
+    }
+  }
+
+  // Colorbox: This event triggers when the transition has completed and the
+  // newly loaded content has been revealed.
+  $(document).bind("cbox_complete", function () {
+    var href = $.colorbox.element().attr("href");
+    if (href) {
+      ga("send", "pageview", { "page": Drupal.googleanalytics.getPageUrl(href) });
+    }
+  });
+
+});
+
+/**
+ * Check whether the hostname is part of the cross domains or not.
+ *
+ * @param string hostname
+ *   The hostname of the clicked URL.
+ * @param array crossDomains
+ *   All cross domain hostnames as JS array.
+ *
+ * @return boolean
+ */
+Drupal.googleanalytics.isCrossDomain = function (hostname, crossDomains) {
+  /**
+   * jQuery < 1.6.3 bug: $.inArray crushes IE6 and Chrome if second argument is
+   * `null` or `undefined`, http://bugs.jquery.com/ticket/10076,
+   * https://github.com/jquery/jquery/commit/a839af034db2bd934e4d4fa6758a3fed8de74174
+   *
+   * @todo: Remove/Refactor in D8
+   */
+  if (!crossDomains) {
+    return false;
+  }
+  else {
+    return $.inArray(hostname, crossDomains) > -1 ? true : false;
+  }
+};
+
+/**
+ * Check whether this is a download URL or not.
+ *
+ * @param string url
+ *   The web url to check.
+ *
+ * @return boolean
+ */
+Drupal.googleanalytics.isDownload = function (url) {
+  var isDownload = new RegExp("\\.(" + Drupal.settings.googleanalytics.trackDownloadExtensions + ")([\?#].*)?$", "i");
+  return isDownload.test(url);
+};
+
+/**
+ * Check whether this is an absolute internal URL or not.
+ *
+ * @param string url
+ *   The web url to check.
+ *
+ * @return boolean
+ */
+Drupal.googleanalytics.isInternal = function (url) {
+  var isInternal = new RegExp("^(https?):\/\/" + window.location.host, "i");
+  return isInternal.test(url);
+};
+
+/**
+ * Check whether this is a special URL or not.
+ *
+ * URL types:
+ *  - gotwo.module /go/* links.
+ *
+ * @param string url
+ *   The web url to check.
+ *
+ * @return boolean
+ */
+Drupal.googleanalytics.isInternalSpecial = function (url) {
+  var isInternalSpecial = new RegExp("(\/go\/.*)$", "i");
+  return isInternalSpecial.test(url);
+};
+
+/**
+ * Extract the relative internal URL from an absolute internal URL.
+ *
+ * Examples:
+ * - http://mydomain.com/node/1 -> /node/1
+ * - http://example.com/foo/bar -> http://example.com/foo/bar
+ *
+ * @param string url
+ *   The web url to check.
+ *
+ * @return string
+ *   Internal website URL
+ */
+Drupal.googleanalytics.getPageUrl = function (url) {
+  var extractInternalUrl = new RegExp("^(https?):\/\/" + window.location.host, "i");
+  return url.replace(extractInternalUrl, '');
+};
+
+/**
+ * Extract the download file extension from the URL.
+ *
+ * @param string url
+ *   The web url to check.
+ *
+ * @return string
+ *   The file extension of the passed url. e.g. "zip", "txt"
+ */
+Drupal.googleanalytics.getDownloadExtension = function (url) {
+  var extractDownloadextension = new RegExp("\\.(" + Drupal.settings.googleanalytics.trackDownloadExtensions + ")([\?#].*)?$", "i");
+  var extension = extractDownloadextension.exec(url);
+  return (extension === null) ? '' : extension[1];
+};
+
+})(jQuery);

+ 670 - 0
sites/all/modules/contrib/admin/google_analytics/googleanalytics.module

@@ -0,0 +1,670 @@
+<?php
+
+/**
+ * @file
+ * Drupal Module: Google Analytics
+ *
+ * Adds the required Javascript to all your Drupal pages to allow tracking by
+ * the Google Analytics statistics package.
+ *
+ * @author: Alexander Hass <http://drupal.org/user/85918>
+ */
+
+/**
+ * Define the default file extension list that should be tracked as download.
+ */
+define('GOOGLEANALYTICS_TRACKFILES_EXTENSIONS', '7z|aac|arc|arj|asf|asx|avi|bin|csv|doc(x|m)?|dot(x|m)?|exe|flv|gif|gz|gzip|hqx|jar|jpe?g|js|mp(2|3|4|e?g)|mov(ie)?|msi|msp|pdf|phps|png|ppt(x|m)?|pot(x|m)?|pps(x|m)?|ppam|sld(x|m)?|thmx|qtm?|ra(m|r)?|sea|sit|tar|tgz|torrent|txt|wav|wma|wmv|wpd|xls(x|m|b)?|xlt(x|m)|xlam|xml|z|zip');
+
+/**
+ * Define default path exclusion list to remove tracking from admin pages,
+ * see http://drupal.org/node/34970 for more information.
+ */
+define('GOOGLEANALYTICS_PAGES', "admin\nadmin/*\nbatch\nnode/add*\nnode/*/*\nuser/*/*");
+
+/**
+ * Advertise the supported google analytics api details.
+ */
+function googleanalytics_api() {
+  return array(
+    'api' => 'analytics.js',
+  );
+}
+
+/**
+ * Implements hook_help().
+ */
+function googleanalytics_help($path, $arg) {
+  switch ($path) {
+    case 'admin/config/system/googleanalytics':
+      return t('<a href="@ga_url">Google Analytics</a> is a free (registration required) website traffic and marketing effectiveness service.', array('@ga_url' => 'http://www.google.com/analytics/'));
+  }
+}
+
+/**
+ * Implements hook_theme().
+ */
+function googleanalytics_theme() {
+  return array(
+    'googleanalytics_admin_custom_var_table' => array(
+      'render element' => 'form',
+    ),
+  );
+}
+
+/**
+ * Implements hook_permission().
+ */
+function googleanalytics_permission() {
+  return array(
+    'administer google analytics' => array(
+      'title' => t('Administer Google Analytics'),
+      'description' => t('Perform maintenance tasks for Google Analytics.'),
+    ),
+    'opt-in or out of tracking' => array(
+      'title' => t('Opt-in or out of tracking'),
+      'description' => t('Allow users to decide if tracking code will be added to pages or not.'),
+    ),
+    'use PHP for tracking visibility' => array(
+      'title' => t('Use PHP for tracking visibility'),
+      'description' => t('Enter PHP code in the field for tracking visibility settings.'),
+      'restrict access' => TRUE,
+    ),
+  );
+}
+
+/**
+ * Implements hook_menu().
+ */
+function googleanalytics_menu() {
+  $items['admin/config/system/googleanalytics'] = array(
+    'title' => 'Google Analytics',
+    'description' => 'Configure tracking behavior to get insights into your website traffic and marketing effectiveness.',
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('googleanalytics_admin_settings_form'),
+    'access arguments' => array('administer google analytics'),
+    'type' => MENU_NORMAL_ITEM,
+    'file' => 'googleanalytics.admin.inc',
+  );
+
+  return $items;
+}
+
+/**
+ * Implements hook_page_alter() to insert JavaScript to the appropriate scope/region of the page.
+ */
+function googleanalytics_page_alter(&$page) {
+  global $user;
+
+  $id = variable_get('googleanalytics_account', '');
+
+  // Get page status code for visibility filtering.
+  $status = drupal_get_http_header('Status');
+  $trackable_status_codes = array(
+    '403 Forbidden',
+    '404 Not Found',
+  );
+
+  // 1. Check if the GA account number has a valid value.
+  // 2. Track page views based on visibility value.
+  // 3. Check if we should track the currently active user's role.
+  // 4. Ignore pages visibility filter for 404 or 403 status codes.
+  if (preg_match('/^UA-\d+-\d+$/', $id) && (_googleanalytics_visibility_pages() || in_array($status, $trackable_status_codes)) && _googleanalytics_visibility_user($user)) {
+
+    $debug = variable_get('googleanalytics_debug', 0);
+    $url_custom = '';
+
+    // Add link tracking.
+    $link_settings = array();
+    if ($track_outbound = variable_get('googleanalytics_trackoutbound', 1)) {
+      $link_settings['trackOutbound'] = $track_outbound;
+    }
+    if ($track_mailto = variable_get('googleanalytics_trackmailto', 1)) {
+      $link_settings['trackMailto'] = $track_mailto;
+    }
+    if (($track_download = variable_get('googleanalytics_trackfiles', 1)) && ($trackfiles_extensions = variable_get('googleanalytics_trackfiles_extensions', GOOGLEANALYTICS_TRACKFILES_EXTENSIONS))) {
+      $link_settings['trackDownload'] = $track_download;
+      $link_settings['trackDownloadExtensions'] = $trackfiles_extensions;
+    }
+    if ($track_domain_mode = variable_get('googleanalytics_domain_mode', 0)) {
+      $link_settings['trackDomainMode'] = $track_domain_mode;
+    }
+    if ($track_cross_domains = variable_get('googleanalytics_cross_domains', '')) {
+      $link_settings['trackCrossDomains'] = preg_split('/(\r\n?|\n)/', $track_cross_domains);
+    }
+    if ($track_url_fragments = variable_get('googleanalytics_trackurlfragments', 0)) {
+      $link_settings['trackUrlFragments'] = $track_url_fragments;
+      $url_custom = 'location.pathname + location.search + location.hash';
+    }
+
+    if (!empty($link_settings)) {
+      drupal_add_js(array('googleanalytics' => $link_settings), 'setting');
+
+      // Add debugging code.
+      if ($debug) {
+        drupal_add_js(drupal_get_path('module', 'googleanalytics') . '/googleanalytics.debug.js');
+        // Add the JS test in development to the page.
+        //drupal_add_js(drupal_get_path('module', 'googleanalytics') . '/googleanalytics.test.js');
+      }
+      else {
+        drupal_add_js(drupal_get_path('module', 'googleanalytics') . '/googleanalytics.js');
+      }
+    }
+
+    // Add messages tracking.
+    $message_events = '';
+    if ($message_types = variable_get('googleanalytics_trackmessages', array())) {
+      $message_types = array_values(array_filter($message_types));
+      $status_heading = array(
+        'status' => t('Status message'),
+        'warning' => t('Warning message'),
+        'error' => t('Error message'),
+      );
+
+      foreach (drupal_get_messages(NULL, FALSE) as $type => $messages) {
+        // Track only the selected message types.
+        if (in_array($type, $message_types)) {
+          foreach ($messages as $message) {
+            // @todo: Track as exceptions?
+            $message_events .= 'ga("send", "event", ' . drupal_json_encode(t('Messages')) . ', ' . drupal_json_encode($status_heading[$type]) . ', ' . drupal_json_encode(strip_tags($message)) . ');';
+          }
+        }
+      }
+    }
+
+    // Site search tracking support.
+    if (module_exists('search') && variable_get('googleanalytics_site_search', FALSE) && arg(0) == 'search' && $keys = googleanalytics_search_get_keys()) {
+      // hook_preprocess_search_results() is not executed if search result is
+      // empty. Make sure the counter is set to 0 if there are no results.
+      $url_custom = '(window.googleanalytics_search_results) ? ' . drupal_json_encode(url('search/' . arg(1), array('query' => array('search' => $keys)))) . ' : ' . drupal_json_encode(url('search/' . arg(1), array('query' => array('search' => 'no-results:' . $keys, 'cat' => 'no-results'))));
+    }
+
+    // If this node is a translation of another node, pass the original
+    // node instead.
+    if (module_exists('translation') && variable_get('googleanalytics_translation_set', 0)) {
+      // Check we have a node object, it supports translation, and its
+      // translated node ID (tnid) doesn't match its own node ID.
+      $node = menu_get_object();
+      if ($node && translation_supported_type($node->type) && !empty($node->tnid) && ($node->tnid != $node->nid)) {
+        $source_node = node_load($node->tnid);
+        $languages = language_list();
+        $url_custom = drupal_json_encode(url('node/' . $source_node->nid, array('language' => $languages[$source_node->language])));
+      }
+    }
+
+    // Track access denied (403) and file not found (404) pages.
+    if ($status == '403 Forbidden') {
+      // See http://www.google.com/support/analytics/bin/answer.py?answer=86927
+      $url_custom = '"/403.html?page=" + document.location.pathname + document.location.search + "&from=" + document.referrer';
+    }
+    elseif ($status == '404 Not Found') {
+      $url_custom = '"/404.html?page=" + document.location.pathname + document.location.search + "&from=" + document.referrer';
+    }
+
+    // Add custom dimensions and metrics.
+    $custom_var = '';
+    foreach (array('dimension', 'metric') as $googleanalytics_custom_type) {
+      $googleanalytics_custom_vars = variable_get('googleanalytics_custom_' . $googleanalytics_custom_type, array());
+      // Are there dimensions or metrics configured?
+      if (!empty($googleanalytics_custom_vars)) {
+        // Add all the configured variables to the content.
+        foreach ($googleanalytics_custom_vars as $googleanalytics_custom_var) {
+          // Replace tokens in values.
+          $types = array();
+          $node = menu_get_object();
+          if (is_object($node)) {
+            $types += array('node' => $node);
+          }
+          $googleanalytics_custom_var['value'] = token_replace($googleanalytics_custom_var['value'], $types, array('clear' => TRUE));
+
+          // Suppress empty values.
+          if (!drupal_strlen(trim($googleanalytics_custom_var['value']))) {
+            continue;
+          }
+
+          // Per documentation the max length of a dimension is 150 bytes.
+          // A metric has no length limitation. It's not documented if this
+          // limit means 150 bytes after url encoding or before.
+          // See https://developers.google.com/analytics/devguides/collection/analyticsjs/field-reference#customs
+          if ($googleanalytics_custom_type == 'dimension' && drupal_strlen($googleanalytics_custom_var['value']) > 150) {
+            $googleanalytics_custom_var['value'] = substr($googleanalytics_custom_var['value'], 0, 150);
+          }
+
+          // Cast metric values for json_encode to data type numeric.
+          if ($googleanalytics_custom_type == 'metric') {
+            settype($googleanalytics_custom_var['value'], 'float');
+          };
+
+          // Add variables to tracker.
+          $custom_var .= 'ga("set", ' . drupal_json_encode($googleanalytics_custom_type . $googleanalytics_custom_var['index']) . ', ' . drupal_json_encode($googleanalytics_custom_var['value']) . ');';
+        }
+      }
+    }
+
+    // Build tracker code.
+    $script = '(function(i,s,o,g,r,a,m){';
+    $script .= 'i["GoogleAnalyticsObject"]=r;i[r]=i[r]||function(){';
+    $script .= '(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),';
+    $script .= 'm=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)';
+    $script .= '})(window,document,"script",';
+
+    // Which version of the tracking library should be used?
+    $library_tracker_url = '//www.google-analytics.com/' . ($debug ? 'analytics_debug.js' : 'analytics.js');
+    $library_cache_url = 'http:' . $library_tracker_url;
+
+    // Should a local cached copy of analytics.js be used?
+    if (variable_get('googleanalytics_cache', 0) && $url = _googleanalytics_cache($library_cache_url)) {
+      // A dummy query-string is added to filenames, to gain control over
+      // browser-caching. The string changes on every update or full cache
+      // flush, forcing browsers to load a new copy of the files, as the
+      // URL changed.
+      $query_string = '?' . variable_get('css_js_query_string', '0');
+
+      $script .= '"' . $url . $query_string . '"';
+    }
+    else {
+      $script .= '"' . $library_tracker_url . '"';
+    }
+    $script .= ',"ga");';
+
+    // Add any custom code snippets if specified.
+    $codesnippet_create = variable_get('googleanalytics_codesnippet_create', array());
+    $codesnippet_before = variable_get('googleanalytics_codesnippet_before', '');
+    $codesnippet_after = variable_get('googleanalytics_codesnippet_after', '');
+
+    // Build the create only fields list.
+    $create_only_fields = array('cookieDomain' => 'auto');
+    $create_only_fields = array_merge($create_only_fields, $codesnippet_create);
+
+    // Domain tracking type.
+    global $cookie_domain;
+    $domain_mode = variable_get('googleanalytics_domain_mode', 0);
+    $googleanalytics_adsense_script = '';
+
+    // Per RFC 2109, cookie domains must contain at least one dot other than the
+    // first. For hosts such as 'localhost' or IP Addresses we don't set a cookie domain.
+    if ($domain_mode == 1 && count(explode('.', $cookie_domain)) > 2 && !is_numeric(str_replace('.', '', $cookie_domain))) {
+      $create_only_fields = array_merge($create_only_fields, array('cookieDomain' => $cookie_domain));
+      $googleanalytics_adsense_script .= 'window.google_analytics_domain_name = ' . drupal_json_encode($cookie_domain) . ';';
+    }
+    elseif ($domain_mode == 2) {
+      // Cross Domain tracking. 'autoLinker' need to be enabled in 'create'.
+      $create_only_fields = array_merge($create_only_fields, array('allowLinker' => TRUE));
+      $googleanalytics_adsense_script .= 'window.google_analytics_domain_name = "none";';
+    }
+
+    // Track logged in users across all devices.
+    if (variable_get('googleanalytics_trackuserid', 0) && user_is_logged_in()) {
+      // The USER_ID value should be a unique, persistent, and non-personally
+      // identifiable string identifier that represents a user or signed-in
+      // account across devices.
+      $create_only_fields['userId'] = drupal_hmac_base64($user->uid, drupal_get_private_key() . drupal_get_hash_salt());
+    }
+
+    // Create a tracker.
+    $script .= 'ga("create", ' . drupal_json_encode($id) . ', ' . drupal_json_encode($create_only_fields) .');';
+
+    // Prepare Adsense tracking.
+    $googleanalytics_adsense_script .= 'window.google_analytics_uacct = ' . drupal_json_encode($id) . ';';
+
+    // Add enhanced link attribution after 'create', but before 'pageview' send.
+    // @see https://support.google.com/analytics/answer/2558867
+    if (variable_get('googleanalytics_tracklinkid', 0)) {
+      $script .= 'ga("require", "linkid", "linkid.js");';
+    }
+
+    // Add display features after 'create', but before 'pageview' send.
+    // @see https://support.google.com/analytics/answer/2444872
+    if (variable_get('googleanalytics_trackdoubleclick', 0)) {
+      $script .= 'ga("require", "displayfeatures");';
+    }
+
+    // Domain tracking type.
+    if ($domain_mode == 2) {
+      // Cross Domain tracking
+      // https://developers.google.com/analytics/devguides/collection/upgrade/reference/gajs-analyticsjs#cross-domain
+      $script .= 'ga("require", "linker");';
+      $script .= 'ga("linker:autoLink", ' . drupal_json_encode($link_settings['trackCrossDomains']) . ');';
+    }
+
+    if (variable_get('googleanalytics_tracker_anonymizeip', 1)) {
+      $script .= 'ga("set", "anonymizeIp", true);';
+    }
+
+    if (!empty($custom_var)) {
+      $script .= $custom_var;
+    }
+    if (!empty($codesnippet_before)) {
+      $script .= $codesnippet_before;
+    }
+    if (!empty($url_custom)) {
+      $script .= 'ga("set", "page", ' . $url_custom . ');';
+    }
+    $script .= 'ga("send", "pageview");';
+
+    if (!empty($message_events)) {
+      $script .= $message_events;
+    }
+    if (!empty($codesnippet_after)) {
+      $script .= $codesnippet_after;
+    }
+
+    if (variable_get('googleanalytics_trackadsense', FALSE)) {
+      // Custom tracking. Prepend before all other JavaScript.
+      // @TODO: https://support.google.com/adsense/answer/98142
+      // sounds like it could be appended to $script.
+      drupal_add_js($googleanalytics_adsense_script, array('type' => 'inline', 'group' => JS_LIBRARY-1));
+    }
+
+    drupal_add_js($script, array('scope' => 'header', 'type' => 'inline'));
+  }
+}
+
+/**
+ * Implements hook_field_extra_fields().
+ */
+function googleanalytics_field_extra_fields() {
+  $extra['user']['user']['form']['googleanalytics'] = array(
+    'label' => t('Google Analytics configuration'),
+    'description' => t('Google Analytics module form element.'),
+    'weight' => 3,
+  );
+
+  return $extra;
+}
+
+/**
+ * Implements hook_form_FORM_ID_alter().
+ *
+ * Allow users to decide if tracking code will be added to pages or not.
+ */
+function googleanalytics_form_user_profile_form_alter(&$form, &$form_state) {
+  $account = $form['#user'];
+  $category = $form['#user_category'];
+
+  if ($category == 'account' && user_access('opt-in or out of tracking') && ($custom = variable_get('googleanalytics_custom', 0)) != 0 && _googleanalytics_visibility_roles($account)) {
+    $form['googleanalytics'] = array(
+      '#type' => 'fieldset',
+      '#title' => t('Google Analytics configuration'),
+      '#weight' => 3,
+      '#collapsible' => TRUE,
+      '#tree' => TRUE
+    );
+
+    switch ($custom) {
+      case 1:
+        $description = t('Users are tracked by default, but you are able to opt out.');
+        break;
+
+      case 2:
+        $description = t('Users are <em>not</em> tracked by default, but you are able to opt in.');
+        break;
+    }
+
+    // Disable tracking for visitors who have opted out from tracking via DNT (Do-Not-Track) header.
+    $disabled = FALSE;
+    if (variable_get('googleanalytics_privacy_donottrack', 1) && !empty($_SERVER['HTTP_DNT'])) {
+      $disabled = TRUE;
+
+      // Override settings value.
+      $account->data['googleanalytics']['custom'] = FALSE;
+
+      $description .= '<span class="admin-disabled">';
+      $description .= ' ' . t('You have opted out from tracking via browser privacy settings.');
+      $description .= '</span>';
+    }
+
+    $form['googleanalytics']['custom'] = array(
+      '#type' => 'checkbox',
+      '#title' => t('Enable user tracking'),
+      '#description' => $description,
+      '#default_value' => isset($account->data['googleanalytics']['custom']) ? $account->data['googleanalytics']['custom'] : ($custom == 1),
+      '#disabled' => $disabled,
+    );
+
+    return $form;
+  }
+}
+
+/**
+ * Implements hook_user_presave().
+ */
+function googleanalytics_user_presave(&$edit, $account, $category) {
+  if (isset($edit['googleanalytics']['custom'])) {
+    $edit['data']['googleanalytics']['custom'] = $edit['googleanalytics']['custom'];
+  }
+}
+
+/**
+ * Implements hook_cron().
+ */
+function googleanalytics_cron() {
+  // Regenerate the tracking code file every day.
+  if (REQUEST_TIME - variable_get('googleanalytics_last_cache', 0) >= 86400 && variable_get('googleanalytics_cache', 0)) {
+    _googleanalytics_cache('http://www.google-analytics.com/analytics.js', TRUE);
+    variable_set('googleanalytics_last_cache', REQUEST_TIME);
+  }
+}
+
+/**
+ * Implements hook_preprocess_search_results().
+ *
+ * Collects and adds the number of search results to the head.
+ */
+function googleanalytics_preprocess_search_results(&$variables) {
+  if (variable_get('googleanalytics_site_search', FALSE)) {
+    // There is no search result $variable available that hold the number of items
+    // found. But the pager item mumber can tell the number of search results.
+    global $pager_total_items;
+
+    drupal_add_js('window.googleanalytics_search_results = ' . intval($pager_total_items[0]) . ';', array('type' => 'inline', 'group' => JS_LIBRARY-1));
+  }
+}
+
+/**
+ * Helper function for grabbing search keys. Function is missing in D7.
+ *
+ * http://api.drupal.org/api/function/search_get_keys/6
+ */
+function googleanalytics_search_get_keys() {
+  static $return;
+  if (!isset($return)) {
+    // Extract keys as remainder of path
+    // Note: support old GET format of searches for existing links.
+    $path = explode('/', $_GET['q'], 3);
+    $keys = empty($_REQUEST['keys']) ? '' : $_REQUEST['keys'];
+    $return = count($path) == 3 ? $path[2] : $keys;
+  }
+  return $return;
+}
+
+/**
+ * Download/Synchronize/Cache tracking code file locally.
+ *
+ * @param $location
+ *   The full URL to the external javascript file.
+ * @param $synchronize
+ *   Synchronize to local cache if remote file has changed.
+ * @return mixed
+ *   The path to the local javascript file on success, boolean FALSE on failure.
+ */
+function _googleanalytics_cache($location, $synchronize = FALSE) {
+  $path = 'public://googleanalytics';
+  $file_destination = $path . '/' . basename($location);
+
+  if (!file_exists($file_destination) || $synchronize) {
+    // Download the latest tracking code.
+    $result = drupal_http_request($location);
+
+    if ($result->code == 200) {
+      if (file_exists($file_destination)) {
+        // Synchronize tracking code and and replace local file if outdated.
+        $data_hash_local = drupal_hash_base64(file_get_contents($file_destination));
+        $data_hash_remote = drupal_hash_base64($result->data);
+        // Check that the files directory is writable.
+        if ($data_hash_local != $data_hash_remote && file_prepare_directory($path)) {
+          // Save updated tracking code file to disk.
+          file_unmanaged_save_data($result->data, $file_destination, FILE_EXISTS_REPLACE);
+          watchdog('googleanalytics', 'Locally cached tracking code file has been updated.', array(), WATCHDOG_INFO);
+
+          // Change query-strings on css/js files to enforce reload for all users.
+          _drupal_flush_css_js();
+        }
+      }
+      else {
+        // Check that the files directory is writable.
+        if (file_prepare_directory($path, FILE_CREATE_DIRECTORY)) {
+          // There is no need to flush JS here as core refreshes JS caches
+          // automatically, if new files are added.
+          file_unmanaged_save_data($result->data, $file_destination, FILE_EXISTS_REPLACE);
+          watchdog('googleanalytics', 'Locally cached tracking code file has been saved.', array(), WATCHDOG_INFO);
+
+          // Return the local JS file path.
+          return file_create_url($file_destination);
+        }
+      }
+    }
+  }
+  else {
+    // Return the local JS file path.
+    return file_create_url($file_destination);
+  }
+}
+
+/**
+ * Delete cached files and directory.
+ */
+function googleanalytics_clear_js_cache() {
+  $path = 'public://googleanalytics';
+  if (file_prepare_directory($path)) {
+    file_scan_directory($path, '/.*/', array('callback' => 'file_unmanaged_delete'));
+    drupal_rmdir($path);
+
+    // Change query-strings on css/js files to enforce reload for all users.
+    _drupal_flush_css_js();
+
+    watchdog('googleanalytics', 'Local cache has been purged.', array(), WATCHDOG_INFO);
+  }
+}
+
+/**
+ * Tracking visibility check for an user object.
+ *
+ * @param $account
+ *   A user object containing an array of roles to check.
+ * @return boolean
+ *   A decision on if the current user is being tracked by Google Analytics.
+ */
+function _googleanalytics_visibility_user($account) {
+
+  $enabled = FALSE;
+
+  // Is current user a member of a role that should be tracked?
+  if (_googleanalytics_visibility_header($account) && _googleanalytics_visibility_roles($account)) {
+
+    // Use the user's block visibility setting, if necessary.
+    if (($custom = variable_get('googleanalytics_custom', 0)) != 0) {
+      if ($account->uid && isset($account->data['googleanalytics']['custom'])) {
+        $enabled = $account->data['googleanalytics']['custom'];
+      }
+      else {
+        $enabled = ($custom == 1);
+      }
+    }
+    else {
+      $enabled = TRUE;
+    }
+
+  }
+
+  return $enabled;
+}
+
+/**
+ * Based on visibility setting this function returns TRUE if GA code should
+ * be added for the current role and otherwise FALSE.
+ */
+function _googleanalytics_visibility_roles($account) {
+
+  $visibility = variable_get('googleanalytics_visibility_roles', 0);
+  $enabled = $visibility;
+  $roles = variable_get('googleanalytics_roles', array());
+
+  if (array_sum($roles) > 0) {
+    // One or more roles are selected.
+    foreach (array_keys($account->roles) as $rid) {
+      // Is the current user a member of one of these roles?
+      if (isset($roles[$rid]) && $rid == $roles[$rid]) {
+        // Current user is a member of a role that should be tracked/excluded from tracking.
+        $enabled = !$visibility;
+        break;
+      }
+    }
+  }
+  else {
+    // No role is selected for tracking, therefore all roles should be tracked.
+    $enabled = TRUE;
+  }
+
+  return $enabled;
+}
+
+/**
+ * Based on visibility setting this function returns TRUE if GA code should
+ * be added to the current page and otherwise FALSE.
+ */
+function _googleanalytics_visibility_pages() {
+  static $page_match;
+
+  // Cache visibility result if function is called more than once.
+  if (!isset($page_match)) {
+
+    $visibility = variable_get('googleanalytics_visibility_pages', 0);
+    $setting_pages = variable_get('googleanalytics_pages', GOOGLEANALYTICS_PAGES);
+
+    // Match path if necessary.
+    if (!empty($setting_pages)) {
+      // Convert path to lowercase. This allows comparison of the same path
+      // with different case. Ex: /Page, /page, /PAGE.
+      $pages = drupal_strtolower($setting_pages);
+      if ($visibility < 2) {
+        // Convert the Drupal path to lowercase
+        $path = drupal_strtolower(drupal_get_path_alias($_GET['q']));
+        // Compare the lowercase internal and lowercase path alias (if any).
+        $page_match = drupal_match_path($path, $pages);
+        if ($path != $_GET['q']) {
+          $page_match = $page_match || drupal_match_path($_GET['q'], $pages);
+        }
+        // When $visibility has a value of 0, the tracking code is displayed on
+        // all pages except those listed in $pages. When set to 1, it
+        // is displayed only on those pages listed in $pages.
+        $page_match = !($visibility xor $page_match);
+      }
+      elseif (module_exists('php')) {
+        $page_match = php_eval($setting_pages);
+      }
+      else {
+        $page_match = FALSE;
+      }
+    }
+    else {
+      $page_match = TRUE;
+    }
+
+  }
+  return $page_match;
+}
+
+/**
+ * Based on headers send by clients this function returns TRUE if GA code should
+ * be added to the current page and otherwise FALSE.
+ */
+function _googleanalytics_visibility_header($account) {
+
+  if (($account->uid || variable_get('cache', 0) == 0) && variable_get('googleanalytics_privacy_donottrack', 1) && !empty($_SERVER['HTTP_DNT'])) {
+    // Disable tracking if caching is disabled or a visitors is logged in and
+    // have opted out from tracking via DNT (Do-Not-Track) header.
+    return FALSE;
+  }
+
+  return TRUE;
+}

+ 721 - 0
sites/all/modules/contrib/admin/google_analytics/googleanalytics.test

@@ -0,0 +1,721 @@
+<?php
+
+/**
+ * @file
+ * Test file for Google Analytics module.
+ */
+class GoogleAnalyticsBasicTest extends DrupalWebTestCase {
+
+  public static function getInfo() {
+    return array(
+      'name' => 'Google Analytics basic tests',
+      'description' => 'Test basic functionality of Google Analytics module.',
+      'group' => 'Google Analytics',
+    );
+  }
+
+  function setUp() {
+    parent::setUp('googleanalytics');
+
+    $permissions = array(
+      'access administration pages',
+      'administer google analytics',
+      'administer modules',
+      'administer site configuration',
+    );
+
+    // User to set up google_analytics.
+    $this->admin_user = $this->drupalCreateUser($permissions);
+    $this->drupalLogin($this->admin_user);
+  }
+
+  function testGoogleAnalyticsConfiguration() {
+    // Check if Configure link is available on 'Modules' page.
+    // Requires 'administer modules' permission.
+    $this->drupalGet('admin/modules');
+    $this->assertRaw('admin/config/system/googleanalytics', '[testGoogleAnalyticsConfiguration]: Configure link from Modules page to Google Analytics Settings page exists.');
+
+    // Check if Configure link is available on 'Status Reports' page. NOTE: Link is only shown without UA code configured.
+    // Requires 'administer site configuration' permission.
+    $this->drupalGet('admin/reports/status');
+    $this->assertRaw('admin/config/system/googleanalytics', '[testGoogleAnalyticsConfiguration]: Configure link from Status Reports page to Google Analytics Settings page exists.');
+
+    // Check for setting page's presence.
+    $this->drupalGet('admin/config/system/googleanalytics');
+    $this->assertRaw(t('Web Property ID'), '[testGoogleAnalyticsConfiguration]: Settings page displayed.');
+
+    // Check for account code validation.
+    $edit['googleanalytics_account'] = $this->randomName(2);
+    $this->drupalPost('admin/config/system/googleanalytics', $edit, t('Save configuration'));
+    $this->assertRaw(t('A valid Google Analytics Web Property ID is case sensitive and formatted like UA-xxxxxxx-yy.'), '[testGoogleAnalyticsConfiguration]: Invalid Web Property ID number validated.');
+  }
+
+  function testGoogleAnalyticsPageVisibility() {
+    // Verify that no tracking code is embedded into the webpage; if there is
+    // only the module installed, but UA code not configured. See #2246991.
+    $this->drupalGet('');
+    $this->assertNoRaw('//www.google-analytics.com/analytics.js', '[testGoogleAnalyticsPageVisibility]: Tracking code is not displayed without UA code configured.');
+
+    $ua_code = 'UA-123456-1';
+    variable_set('googleanalytics_account', $ua_code);
+
+    // Show tracking on "every page except the listed pages".
+    variable_set('googleanalytics_visibility_pages', 0);
+    // Disable tracking on "admin*" pages only.
+    variable_set('googleanalytics_pages', "admin\nadmin/*");
+    // Enable tracking only for authenticated users only.
+    variable_set('googleanalytics_roles', array(DRUPAL_AUTHENTICATED_RID => DRUPAL_AUTHENTICATED_RID));
+
+    // Check tracking code visibility.
+    $this->drupalGet('');
+    $this->assertRaw($ua_code, '[testGoogleAnalyticsPageVisibility]: Tracking code is displayed for authenticated users.');
+
+    // Test whether tracking code is not included on pages to omit.
+    $this->drupalGet('admin');
+    $this->assertNoRaw($ua_code, '[testGoogleAnalyticsPageVisibility]: Tracking code is not displayed on admin page.');
+    $this->drupalGet('admin/config/system/googleanalytics');
+    // Checking for tracking code URI here, as $ua_code is displayed in the form.
+    $this->assertNoRaw('//www.google-analytics.com/analytics.js', '[testGoogleAnalyticsPageVisibility]: Tracking code is not displayed on admin subpage.');
+
+    // Test whether tracking code display is properly flipped.
+    variable_set('googleanalytics_visibility_pages', 1);
+    $this->drupalGet('admin');
+    $this->assertRaw($ua_code, '[testGoogleAnalyticsPageVisibility]: Tracking code is displayed on admin page.');
+    $this->drupalGet('admin/config/system/googleanalytics');
+    // Checking for tracking code URI here, as $ua_code is displayed in the form.
+    $this->assertRaw('//www.google-analytics.com/analytics.js', '[testGoogleAnalyticsPageVisibility]: Tracking code is displayed on admin subpage.');
+    $this->drupalGet('');
+    $this->assertNoRaw($ua_code, '[testGoogleAnalyticsPageVisibility]: Tracking code is NOT displayed on front page.');
+
+    // Test whether tracking code is not display for anonymous.
+    $this->drupalLogout();
+    $this->drupalGet('');
+    $this->assertNoRaw($ua_code, '[testGoogleAnalyticsPageVisibility]: Tracking code is NOT displayed for anonymous.');
+
+    // Switch back to every page except the listed pages.
+    variable_set('googleanalytics_visibility_pages', 0);
+    // Enable tracking code for all user roles.
+    variable_set('googleanalytics_roles', array());
+
+    // Test whether 403 forbidden tracking code is shown if user has no access.
+    $this->drupalGet('admin');
+    $this->assertRaw('/403.html', '[testGoogleAnalyticsPageVisibility]: 403 Forbidden tracking code shown if user has no access.');
+
+    // Test whether 404 not found tracking code is shown on non-existent pages.
+    $this->drupalGet($this->randomName(64));
+    $this->assertRaw('/404.html', '[testGoogleAnalyticsPageVisibility]: 404 Not Found tracking code shown on non-existent page.');
+
+    // DNT Tests:
+    // Enable system internal page cache for anonymous users.
+    variable_set('cache', 1);
+    // Test whether DNT headers will fail to disable embedding of tracking code.
+    $this->drupalGet('', array(), array('DNT: 1'));
+    $this->assertRaw('ga("send", "pageview");', '[testGoogleAnalyticsDNTVisibility]: DNT header send from client, but page caching is enabled and tracker cannot removed.');
+    // DNT works only with system internal page cache for anonymous users disabled.
+    variable_set('cache', 0);
+    $this->drupalGet('');
+    $this->assertRaw('ga("send", "pageview");', '[testGoogleAnalyticsDNTVisibility]: Tracking is enabled without DNT header.');
+    // Test whether DNT header is able to remove the tracking code.
+    $this->drupalGet('', array(), array('DNT: 1'));
+    $this->assertNoRaw('ga("send", "pageview");', '[testGoogleAnalyticsDNTVisibility]: DNT header received from client. Tracking has been disabled by browser.');
+    // Disable DNT feature and see if tracker is still embedded.
+    variable_set('googleanalytics_privacy_donottrack', 0);
+    $this->drupalGet('', array(), array('DNT: 1'));
+    $this->assertRaw('ga("send", "pageview");', '[testGoogleAnalyticsDNTVisibility]: DNT feature is disabled, DNT header from browser has been ignored.');
+  }
+
+  function testGoogleAnalyticsTrackingCode() {
+    $ua_code = 'UA-123456-2';
+    variable_set('googleanalytics_account', $ua_code);
+
+    // Show tracking code on every page except the listed pages.
+    variable_set('googleanalytics_visibility_pages', 0);
+    // Enable tracking code for all user roles.
+    variable_set('googleanalytics_roles', array());
+
+    /* Sample JS code as added to page:
+    <script type="text/javascript" src="/sites/all/modules/google_analytics/googleanalytics.js?w"></script>
+    <script>
+    (function(q,u,i,c,k){window['GoogleAnalyticsObject']=q;
+    window[q]=window[q]||function(){(window[q].q=window[q].q||[]).push(arguments)},
+    window[q].l=1*new Date();c=i.createElement(u),k=i.getElementsByTagName(u)[0];
+    c.async=true;c.src='//www.google-analytics.com/analytics.js';
+    k.parentNode.insertBefore(c,k)})('ga','script',document);
+    ga('create', 'UA-123456-7');
+    ga('send', 'pageview');
+    </script>
+    <!-- End Google Analytics -->
+    */
+
+    // Test whether tracking code uses latest JS.
+    variable_set('googleanalytics_cache', 0);
+    $this->drupalGet('');
+    $this->assertRaw('//www.google-analytics.com/analytics.js', '[testGoogleAnalyticsTrackingCode]: Latest tracking code used.');
+
+    // Test whether anonymize visitors IP address feature has been enabled.
+    variable_set('googleanalytics_tracker_anonymizeip', 0);
+    $this->drupalGet('');
+    $this->assertNoRaw('ga("set", "anonymizeIp", true);', '[testGoogleAnalyticsTrackingCode]: Anonymize visitors IP address not found on frontpage.');
+    // Enable anonymizing of IP addresses.
+    variable_set('googleanalytics_tracker_anonymizeip', 1);
+    $this->drupalGet('');
+    $this->assertRaw('ga("set", "anonymizeIp", true);', '[testGoogleAnalyticsTrackingCode]: Anonymize visitors IP address found on frontpage.');
+
+    // Test if track Enhanced Link Attribution is enabled.
+    variable_set('googleanalytics_tracklinkid', 1);
+    $this->drupalGet('');
+    $this->assertRaw('ga("require", "linkid", "linkid.js");', '[testGoogleAnalyticsTrackingCode]: Tracking code for Enhanced Link Attribution is enabled.');
+
+    // Test if track Enhanced Link Attribution is disabled.
+    variable_set('googleanalytics_tracklinkid', 0);
+    $this->drupalGet('');
+    $this->assertNoRaw('ga("require", "linkid", "linkid.js");', '[testGoogleAnalyticsTrackingCode]: Tracking code for Enhanced Link Attribution is not enabled.');
+
+    // Test if tracking of User ID is enabled.
+    variable_set('googleanalytics_trackuserid', 1);
+    $this->drupalGet('');
+    $this->assertRaw(', {"cookieDomain":"auto","userId":"', '[testGoogleAnalyticsTrackingCode]: Tracking code for User ID is enabled.');
+
+    // Test if tracking of User ID is disabled.
+    variable_set('googleanalytics_trackuserid', 0);
+    $this->drupalGet('');
+    $this->assertNoRaw(', {"cookieDomain":"auto","userId":"', '[testGoogleAnalyticsTrackingCode]: Tracking code for User ID is disabled.');
+
+    // Test if tracking of url fragments is enabled.
+    variable_set('googleanalytics_trackurlfragments', 1);
+    $this->drupalGet('');
+    $this->assertRaw('ga("set", "page", location.pathname + location.search + location.hash);', '[testGoogleAnalyticsTrackingCode]: Tracking code for url fragments is enabled.');
+
+    // Test if tracking of url fragments is disabled.
+    variable_set('googleanalytics_trackurlfragments', 0);
+    $this->drupalGet('');
+    $this->assertNoRaw('ga("set", "page", location.pathname + location.search + location.hash);', '[testGoogleAnalyticsTrackingCode]: Tracking code for url fragments is not enabled.');
+
+    // Test if track display features is enabled.
+    variable_set('googleanalytics_trackdoubleclick', 1);
+    $this->drupalGet('');
+    $this->assertRaw('ga("require", "displayfeatures");', '[testGoogleAnalyticsTrackingCode]: Tracking code for display features is enabled.');
+
+    // Test if track display features is disabled.
+    variable_set('googleanalytics_trackdoubleclick', 0);
+    $this->drupalGet('');
+    $this->assertNoRaw('ga("require", "displayfeatures");', '[testGoogleAnalyticsTrackingCode]: Tracking code for display features is not enabled.');
+
+    // Test whether single domain tracking is active.
+    $this->drupalGet('');
+    $this->assertRaw('{"cookieDomain":"auto"}', '[testGoogleAnalyticsTrackingCode]: Single domain tracking is active.');
+
+    // Enable "One domain with multiple subdomains".
+    variable_set('googleanalytics_domain_mode', 1);
+    $this->drupalGet('');
+
+    // Test may run on localhost, an ipaddress or real domain name.
+    // TODO: Workaround to run tests successfully. This feature cannot tested reliable.
+    global $cookie_domain;
+    if (count(explode('.', $cookie_domain)) > 2 && !is_numeric(str_replace('.', '', $cookie_domain))) {
+      $this->assertRaw('{"cookieDomain":"' . $cookie_domain . '"}', '[testGoogleAnalyticsTrackingCode]: One domain with multiple subdomains is active on real host.');
+    }
+    else {
+      // Special cases, Localhost and IP addresses don't show '_setDomainName'.
+      $this->assertNoRaw('{"cookieDomain":"' . $cookie_domain . '"}', '[testGoogleAnalyticsTrackingCode]: One domain with multiple subdomains may be active on localhost (test result is not reliable).');
+    }
+
+    // Enable "Multiple top-level domains" tracking.
+    variable_set('googleanalytics_domain_mode', 2);
+    variable_set('googleanalytics_cross_domains', "www.example.com\nwww.example.net");
+    $this->drupalGet('');
+    $this->assertRaw('ga("create", "' . $ua_code . '", {"cookieDomain":"auto","allowLinker":true', '[testGoogleAnalyticsTrackingCode]: "allowLinker" has been found. Cross domain tracking is active.');
+    $this->assertRaw('ga("require", "linker");', '[testGoogleAnalyticsTrackingCode]: Require linker has been found. Cross domain tracking is active.');
+    $this->assertRaw('ga("linker:autoLink", ["www.example.com","www.example.net"]);', '[testGoogleAnalyticsTrackingCode]: "linker:autoLink" has been found. Cross domain tracking is active.');
+    $this->assertRaw('"trackCrossDomains":["www.example.com","www.example.net"]', '[testGoogleAnalyticsTrackingCode]: Cross domain tracking with www.example.com and www.example.net is active.');
+    variable_set('googleanalytics_domain_mode', 0);
+
+    // Test whether debugging script has been enabled.
+    variable_set('googleanalytics_debug', 1);
+    $this->drupalGet('');
+    $this->assertRaw('//www.google-analytics.com/analytics_debug.js', '[testGoogleAnalyticsTrackingCode]: Google debugging script has been enabled.');
+
+    // Check if text and link is shown on 'Status Reports' page.
+    // Requires 'administer site configuration' permission.
+    $this->drupalGet('admin/reports/status');
+    $this->assertRaw(t('Google Analytics module has debugging enabled. Please disable debugging setting in production sites from the <a href="@url">Google Analytics settings page</a>.', array('@url' => url('admin/config/system/googleanalytics'))), '[testGoogleAnalyticsConfiguration]: Debugging enabled is shown on Status Reports page.');
+
+    // Test whether debugging script has been disabled.
+    variable_set('googleanalytics_debug', 0);
+    $this->drupalGet('');
+    $this->assertRaw('//www.google-analytics.com/analytics.js', '[testGoogleAnalyticsTrackingCode]: Google debugging script has been disabled.');
+
+    // Test whether the CREATE and BEFORE and AFTER code is added to the tracker.
+    $codesnippet_create = array(
+      'cookieDomain' => 'foo.example.com',
+      'cookieName' => 'myNewName',
+      'cookieExpires' => 20000,
+      'allowAnchor' => TRUE,
+      'sampleRate' => 4.3,
+    );
+    variable_set('googleanalytics_codesnippet_create', $codesnippet_create);
+    variable_set('googleanalytics_codesnippet_before', 'ga("set", "forceSSL", true);');
+    variable_set('googleanalytics_codesnippet_after', 'ga("create", "UA-123456-3", {"name": "newTracker"});ga("newTracker.send", "pageview");');
+    $this->drupalGet('');
+    $this->assertRaw('ga("create", "' . $ua_code . '", {"cookieDomain":"foo.example.com","cookieName":"myNewName","cookieExpires":20000,"allowAnchor":true,"sampleRate":4.3});', '[testGoogleAnalyticsTrackingCode]: Create only fields have been found.');
+    $this->assertRaw('ga("set", "forceSSL", true);', '[testGoogleAnalyticsTrackingCode]: Before codesnippet will force http pages to also send all beacons using https.');
+    $this->assertRaw('ga("create", "UA-123456-3", {"name": "newTracker"});', '[testGoogleAnalyticsTrackingCode]: After codesnippet with "newTracker" tracker has been found.');
+  }
+}
+
+class GoogleAnalyticsCustomDimensionsAndMetricsTest extends DrupalWebTestCase {
+
+  public static function getInfo() {
+    return array(
+      'name' => 'Google Analytics custom dimensions and metrics tests',
+      'description' => 'Test custom dimensions and metrics functionality of Google Analytics module.',
+      'group' => 'Google Analytics',
+      'dependencies' => array('token'),
+    );
+  }
+
+  function setUp() {
+    parent::setUp('googleanalytics', 'token');
+
+    $permissions = array(
+      'access administration pages',
+      'administer google analytics',
+    );
+
+    // User to set up google_analytics.
+    $this->admin_user = $this->drupalCreateUser($permissions);
+  }
+
+  function testGoogleAnalyticsCustomDimensions() {
+    $ua_code = 'UA-123456-3';
+    variable_set('googleanalytics_account', $ua_code);
+
+    // Basic test if the feature works.
+    $googleanalytics_custom_dimension = array(
+      1 => array(
+        'index' => 1,
+        'value' => 'Bar 1',
+      ),
+      2 => array(
+        'index' => 2,
+        'value' => 'Bar 2',
+      ),
+      3 => array(
+        'index' => 3,
+        'value' => 'Bar 3',
+      ),
+      4 => array(
+        'index' => 4,
+        'value' => 'Bar 4',
+      ),
+      5 => array(
+        'index' => 5,
+        'value' => 'Bar 5',
+      ),
+    );
+    variable_set('googleanalytics_custom_dimension', $googleanalytics_custom_dimension);
+    $this->drupalGet('');
+
+    foreach ($googleanalytics_custom_dimension as $dimension) {
+      $this->assertRaw('ga("set", ' . drupal_json_encode('dimension' . $dimension['index']) . ', ' . drupal_json_encode($dimension['value']) . ');', '[testGoogleAnalyticsCustomDimensionsAndMetrics]: Dimension #' . $dimension['index'] . ' is shown.');
+    }
+
+    // Test whether tokens are replaced in custom dimension values.
+    $site_slogan = $this->randomName(16);
+    variable_set('site_slogan', $site_slogan);
+
+    $googleanalytics_custom_dimension = array(
+      1 => array(
+        'index' => 1,
+        'value' => 'Value: [site:slogan]',
+      ),
+      2 => array(
+        'index' => 2,
+        'value' => $this->randomName(16),
+      ),
+      3 => array(
+        'index' => 3,
+        'value' => '',
+      ),
+      // #2300701: Custom dimensions and custom metrics not outputed on zero value.
+      4 => array(
+        'index' => 4,
+        'value' => '0',
+      ),
+    );
+    variable_set('googleanalytics_custom_dimension', $googleanalytics_custom_dimension);
+    $this->verbose('<pre>' . print_r($googleanalytics_custom_dimension, TRUE) . '</pre>');
+
+    $this->drupalGet('');
+    $this->assertRaw('ga("set", ' . drupal_json_encode('dimension1') . ', ' . drupal_json_encode("Value: $site_slogan") . ');', '[testGoogleAnalyticsCustomDimensionsAndMetrics]: Tokens have been replaced in dimension value.');
+    $this->assertRaw('ga("set", ' . drupal_json_encode('dimension2') . ', ' . drupal_json_encode($googleanalytics_custom_dimension['2']['value']) . ');', '[testGoogleAnalyticsCustomDimensionsAndMetrics]: Random value is shown.');
+    $this->assertNoRaw('ga("set", ' . drupal_json_encode('dimension3') . ', ' . drupal_json_encode('') . ');', '[testGoogleAnalyticsCustomDimensionsAndMetrics]: Empty value is not shown.');
+    $this->assertRaw('ga("set", ' . drupal_json_encode('dimension4') . ', ' . drupal_json_encode('0') . ');', '[testGoogleAnalyticsCustomDimensionsAndMetrics]: Value 0 is shown.');
+  }
+
+  function testGoogleAnalyticsCustomMetrics() {
+    $ua_code = 'UA-123456-3';
+    variable_set('googleanalytics_account', $ua_code);
+
+    // Basic test if the feature works.
+    $googleanalytics_custom_metric = array(
+      1 => array(
+        'index' => 1,
+        'value' => '6',
+        'value_expected' => 6,
+      ),
+      2 => array(
+        'index' => 2,
+        'value' => '8000',
+        'value_expected' => 8000,
+      ),
+      3 => array(
+        'index' => 3,
+        'value' => '7.8654',
+        'value_expected' => 7.8654,
+      ),
+      4 => array(
+        'index' => 4,
+        'value' => '1123.4',
+        'value_expected' => 1123.4,
+      ),
+      5 => array(
+        'index' => 5,
+        'value' => '5,67',
+        'value_expected' => 5,
+      ),
+    );
+    variable_set('googleanalytics_custom_metric', $googleanalytics_custom_metric);
+    $this->drupalGet('');
+
+    foreach ($googleanalytics_custom_metric as $metric) {
+      $this->assertRaw('ga("set", ' . drupal_json_encode('metric' . $metric['index']) . ', ' . drupal_json_encode($metric['value_expected']) . ');', '[testGoogleAnalyticsCustomDimensionsAndMetrics]: Metric #' . $metric['index'] . ' is shown.');
+    }
+
+    // Test whether tokens are replaced in custom metric values.
+    $googleanalytics_custom_metric = array(
+      1 => array(
+        'index' => 1,
+        'value' => '[current-user:roles:count]',
+      ),
+      2 => array(
+        'index' => 2,
+        'value' => mt_rand(),
+      ),
+      3 => array(
+        'index' => 3,
+        'value' => '',
+      ),
+      // #2300701: Custom dimensions and custom metrics not outputed on zero value.
+      4 => array(
+        'index' => 4,
+        'value' => '0',
+      ),
+    );
+    variable_set('googleanalytics_custom_metric', $googleanalytics_custom_metric);
+    $this->verbose('<pre>' . print_r($googleanalytics_custom_metric, TRUE) . '</pre>');
+
+    $this->drupalGet('');
+    $this->assertRaw('ga("set", ' . drupal_json_encode('metric1') . ', ', '[testGoogleAnalyticsCustomDimensionsAndMetrics]: Tokens have been replaced in metric value.');
+    $this->assertRaw('ga("set", ' . drupal_json_encode('metric2') . ', ' . drupal_json_encode($googleanalytics_custom_metric['2']['value']) . ');', '[testGoogleAnalyticsCustomDimensionsAndMetrics]: Random value is shown.');
+    $this->assertNoRaw('ga("set", ' . drupal_json_encode('metric3') . ', ' . drupal_json_encode('') . ');', '[testGoogleAnalyticsCustomDimensionsAndMetrics]: Empty value is not shown.');
+    $this->assertRaw('ga("set", ' . drupal_json_encode('metric4') . ', ' . drupal_json_encode(0) . ');', '[testGoogleAnalyticsCustomDimensionsAndMetrics]: Value 0 is shown.');
+  }
+}
+
+class GoogleAnalyticsStatusMessagesTest extends DrupalWebTestCase {
+
+  public static function getInfo() {
+    return array(
+      'name' => 'Google Analytics status messages tests',
+      'description' => 'Test status messages functionality of Google Analytics module.',
+      'group' => 'Google Analytics',
+    );
+  }
+
+  function setUp() {
+    parent::setUp('googleanalytics');
+
+    $permissions = array(
+      'access administration pages',
+      'administer google analytics',
+    );
+
+    // User to set up google_analytics.
+    $this->admin_user = $this->drupalCreateUser($permissions);
+  }
+
+  function testGoogleAnalyticsStatusMessages() {
+    $ua_code = 'UA-123456-4';
+    variable_set('googleanalytics_account', $ua_code);
+
+    // Enable logging of errors only.
+    variable_set('googleanalytics_trackmessages', array('error' => 'error'));
+
+    $this->drupalPost('user/login', array(), t('Log in'));
+    $this->assertRaw('ga("send", "event", "Messages", "Error message", "Username field is required.");', '[testGoogleAnalyticsStatusMessages]: Event message "Username field is required." is shown.');
+    $this->assertRaw('ga("send", "event", "Messages", "Error message", "Password field is required.");', '[testGoogleAnalyticsStatusMessages]: Event message "Password field is required." is shown.');
+
+    // @todo: investigate why drupal_set_message() fails.
+    //drupal_set_message('Example status message.', 'status');
+    //drupal_set_message('Example warning message.', 'warning');
+    //drupal_set_message('Example error message.', 'error');
+    //drupal_set_message('Example error <em>message</em> with html tags and <a href="http://example.com/">link</a>.', 'error');
+    //$this->drupalGet('');
+    //$this->assertNoRaw('ga("send", "event", "Messages", "Status message", "Example status message.");', '[testGoogleAnalyticsStatusMessages]: Example status message is not enabled for tracking.');
+    //$this->assertNoRaw('ga("send", "event", "Messages", "Warning message", "Example warning message.");', '[testGoogleAnalyticsStatusMessages]: Example warning message is not enabled for tracking.');
+    //$this->assertRaw('ga("send", "event", "Messages", "Error message", "Example error message.");', '[testGoogleAnalyticsStatusMessages]: Example error message is shown.');
+    //$this->assertRaw('ga("send", "event", "Messages", "Error message", "Example error message with html tags and link.");', '[testGoogleAnalyticsStatusMessages]: HTML has been stripped successful from Example error message with html tags and link.');
+  }
+}
+
+class GoogleAnalyticsRolesTest extends DrupalWebTestCase {
+
+  public static function getInfo() {
+    return array(
+      'name' => 'Google Analytics role tests',
+      'description' => 'Test roles functionality of Google Analytics module.',
+      'group' => 'Google Analytics',
+    );
+  }
+
+  function setUp() {
+    parent::setUp('googleanalytics');
+
+    $permissions = array(
+      'access administration pages',
+      'administer google analytics',
+    );
+
+    // User to set up google_analytics.
+    $this->admin_user = $this->drupalCreateUser($permissions);
+  }
+
+  function testGoogleAnalyticsRolesTracking() {
+    $ua_code = 'UA-123456-4';
+    variable_set('googleanalytics_account', $ua_code);
+
+    // Test if the default settings are working as expected.
+
+    // Add to the selected roles only.
+    variable_set('googleanalytics_visibility_roles', 0);
+    // Enable tracking for all users.
+    variable_set('googleanalytics_roles', array());
+
+    // Check tracking code visibility.
+    $this->drupalGet('');
+    $this->assertRaw($ua_code, '[testGoogleAnalyticsRoleVisibility]: Tracking code is displayed for anonymous users on frontpage with default settings.');
+    $this->drupalGet('admin');
+    $this->assertRaw('/403.html', '[testGoogleAnalyticsRoleVisibility]: 403 Forbidden tracking code is displayed for anonymous users in admin section with default settings.');
+
+    $this->drupalLogin($this->admin_user);
+
+    $this->drupalGet('');
+    $this->assertRaw($ua_code, '[testGoogleAnalyticsRoleVisibility]: Tracking code is displayed for authenticated users on frontpage with default settings.');
+    $this->drupalGet('admin');
+    $this->assertNoRaw($ua_code, '[testGoogleAnalyticsRoleVisibility]: Tracking code is NOT displayed for authenticated users in admin section with default settings.');
+
+    // Test if the non-default settings are working as expected.
+
+    // Enable tracking only for authenticated users.
+    variable_set('googleanalytics_roles', array(DRUPAL_AUTHENTICATED_RID => DRUPAL_AUTHENTICATED_RID));
+
+    $this->drupalGet('');
+    $this->assertRaw($ua_code, '[testGoogleAnalyticsRoleVisibility]: Tracking code is displayed for authenticated users only on frontpage.');
+
+    $this->drupalLogout();
+    $this->drupalGet('');
+    $this->assertNoRaw($ua_code, '[testGoogleAnalyticsRoleVisibility]: Tracking code is NOT displayed for anonymous users on frontpage.');
+
+    // Add to every role except the selected ones.
+    variable_set('googleanalytics_visibility_roles', 1);
+    // Enable tracking for all users.
+    variable_set('googleanalytics_roles', array());
+
+    // Check tracking code visibility.
+    $this->drupalGet('');
+    $this->assertRaw($ua_code, '[testGoogleAnalyticsRoleVisibility]: Tracking code is added to every role and displayed for anonymous users.');
+    $this->drupalGet('admin');
+    $this->assertRaw('/403.html', '[testGoogleAnalyticsRoleVisibility]: 403 Forbidden tracking code is shown for anonymous users if every role except the selected ones is selected.');
+
+    $this->drupalLogin($this->admin_user);
+
+    $this->drupalGet('');
+    $this->assertRaw($ua_code, '[testGoogleAnalyticsRoleVisibility]: Tracking code is added to every role and displayed on frontpage for authenticated users.');
+    $this->drupalGet('admin');
+    $this->assertNoRaw($ua_code, '[testGoogleAnalyticsRoleVisibility]: Tracking code is added to every role and NOT displayed in admin section for authenticated users.');
+
+    // Disable tracking for authenticated users.
+    variable_set('googleanalytics_roles', array(DRUPAL_AUTHENTICATED_RID => DRUPAL_AUTHENTICATED_RID));
+
+    $this->drupalGet('');
+    $this->assertNoRaw($ua_code, '[testGoogleAnalyticsRoleVisibility]: Tracking code is NOT displayed on frontpage for excluded authenticated users.');
+    $this->drupalGet('admin');
+    $this->assertNoRaw($ua_code, '[testGoogleAnalyticsRoleVisibility]: Tracking code is NOT displayed in admin section for excluded authenticated users.');
+
+    $this->drupalLogout();
+    $this->drupalGet('');
+    $this->assertRaw($ua_code, '[testGoogleAnalyticsRoleVisibility]: Tracking code is displayed on frontpage for included anonymous users.');
+  }
+}
+
+class GoogleAnalyticsSearchTest extends DrupalWebTestCase {
+
+  public static function getInfo() {
+    return array(
+      'name' => 'Google Analytics search tests',
+      'description' => 'Test search functionality of Google Analytics module.',
+      'group' => 'Google Analytics',
+    );
+  }
+
+  function setUp() {
+    parent::setUp('googleanalytics', 'search', 'node');
+
+    $permissions = array(
+      'access administration pages',
+      'administer google analytics',
+      'search content',
+      'create page content',
+      'edit own page content',
+    );
+
+    // User to set up google_analytics.
+    $this->admin_user = $this->drupalCreateUser($permissions);
+    $this->drupalLogin($this->admin_user);
+  }
+
+  function testGoogleAnalyticsSearchTracking() {
+    $ua_code = 'UA-123456-1';
+    variable_set('googleanalytics_account', $ua_code);
+
+    // Check tracking code visibility.
+    $this->drupalGet('');
+    $this->assertRaw($ua_code, '[testGoogleAnalyticsSearch]: Tracking code is displayed for authenticated users.');
+
+    $this->drupalGet('search/node');
+    $this->assertNoRaw('ga("set", "page",', '[testGoogleAnalyticsSearch]: Custom url not set.');
+
+    // Enable site search support.
+    variable_set('googleanalytics_site_search', 1);
+
+    // Search for random string.
+    $search = array();
+    $search['keys'] = $this->randomName(8);
+
+    // Create a node to search for.
+    $langcode = LANGUAGE_NONE;
+    $edit = array();
+    $edit['title'] = 'This is a test title';
+    $edit["body[$langcode][0][value]"] = 'This test content contains ' . $search['keys'] . ' string.';
+
+    // Fire a search, it's expected to get 0 results.
+    $this->drupalPost('search/node', $search, t('Search'));
+    $this->assertRaw('ga("set", "page", (window.googleanalytics_search_results) ?', '[testGoogleAnalyticsSearch]: Search results tracker is displayed.');
+    $this->assertRaw('window.googleanalytics_search_results = 0;', '[testGoogleAnalyticsSearch]: Search yielded no results.');
+
+    // Save the node.
+    $this->drupalPost('node/add/page', $edit, t('Save'));
+    $this->assertText(t('@type @title has been created.', array('@type' => 'Basic page', '@title' => $edit['title'])), 'Node was created.');
+
+    // Index the node or it cannot found.
+    $this->cronRun();
+
+    $this->drupalPost('search/node', $search, t('Search'));
+    $this->assertRaw('ga("set", "page", (window.googleanalytics_search_results) ?', '[testGoogleAnalyticsSearch]: Search results tracker is displayed.');
+    $this->assertRaw('window.googleanalytics_search_results = 1;', '[testGoogleAnalyticsSearch]: One search result found.');
+
+    $this->drupalPost('node/add/page', $edit, t('Save'));
+    $this->assertText(t('@type @title has been created.', array('@type' => 'Basic page', '@title' => $edit['title'])), 'Node was created.');
+
+    // Index the node or it cannot found.
+    $this->cronRun();
+
+    $this->drupalPost('search/node', $search, t('Search'));
+    $this->assertRaw('ga("set", "page", (window.googleanalytics_search_results) ?', '[testGoogleAnalyticsSearch]: Search results tracker is displayed.');
+    $this->assertRaw('window.googleanalytics_search_results = 2;', '[testGoogleAnalyticsSearch]: Two search results found.');
+  }
+
+}
+
+class GoogleAnalyticsPhpFilterTest extends DrupalWebTestCase {
+
+  public static function getInfo() {
+    return array(
+      'name' => 'Google Analytics php filter tests',
+      'description' => 'Test php filter functionality of Google Analytics module.',
+      'group' => 'Google Analytics',
+    );
+  }
+
+  function setUp() {
+    parent::setUp('googleanalytics', 'php');
+
+    // Administrator with all permissions.
+    $permissions_admin_user = array(
+      'access administration pages',
+      'administer google analytics',
+      'use PHP for tracking visibility',
+    );
+    $this->admin_user = $this->drupalCreateUser($permissions_admin_user);
+
+    // Administrator who cannot configure tracking visibility with PHP.
+    $permissions_delegated_admin_user = array(
+      'access administration pages',
+      'administer google analytics',
+    );
+    $this->delegated_admin_user = $this->drupalCreateUser($permissions_delegated_admin_user);
+  }
+
+  function testGoogleAnalyticsPhpFilter() {
+    $ua_code = 'UA-123456-1';
+    $this->drupalLogin($this->admin_user);
+
+    $edit = array();
+    $edit['googleanalytics_account'] = $ua_code;
+    $edit['googleanalytics_visibility_pages'] = 2;
+    $edit['googleanalytics_pages'] = '<?php return 0; ?>';
+    $this->drupalPost('admin/config/system/googleanalytics', $edit, t('Save configuration'));
+
+    // Compare saved setting with posted setting.
+    $googleanalytics_pages = variable_get('googleanalytics_pages', $this->randomName(8));
+    $this->assertEqual('<?php return 0; ?>', $googleanalytics_pages, '[testGoogleAnalyticsPhpFilter]: PHP code snippet is intact.');
+
+    // Check tracking code visibility.
+    variable_set('googleanalytics_pages', '<?php return TRUE; ?>');
+    $this->drupalGet('');
+    $this->assertRaw('//www.google-analytics.com/analytics.js', '[testGoogleAnalyticsPhpFilter]: Tracking is displayed on frontpage page.');
+    $this->drupalGet('admin');
+    $this->assertRaw('//www.google-analytics.com/analytics.js', '[testGoogleAnalyticsPhpFilter]: Tracking is displayed on admin page.');
+
+    variable_set('googleanalytics_pages', '<?php return FALSE; ?>');
+    $this->drupalGet('');
+    $this->assertNoRaw('//www.google-analytics.com/analytics.js', '[testGoogleAnalyticsPhpFilter]: Tracking is not displayed on frontpage page.');
+
+    // Test administration form.
+    variable_set('googleanalytics_pages', '<?php return TRUE; ?>');
+    $this->drupalGet('admin/config/system/googleanalytics');
+    $this->assertRaw(t('Pages on which this PHP code returns <code>TRUE</code> (experts only)'), '[testGoogleAnalyticsPhpFilter]: Permission to administer PHP for tracking visibility.');
+    $this->assertRaw(check_plain('<?php return TRUE; ?>'), '[testGoogleAnalyticsPhpFilter]: PHP code snippted is displayed.');
+
+    // Login the delegated user and check if fields are visible.
+    $this->drupalLogin($this->delegated_admin_user);
+    $this->drupalGet('admin/config/system/googleanalytics');
+    $this->assertNoRaw(t('Pages on which this PHP code returns <code>TRUE</code> (experts only)'), '[testGoogleAnalyticsPhpFilter]: No permission to administer PHP for tracking visibility.');
+    $this->assertNoRaw(check_plain('<?php return TRUE; ?>'), '[testGoogleAnalyticsPhpFilter]: No permission to view PHP code snippted.');
+
+    // Set a different value and verify that this is still the same after the post.
+    variable_set('googleanalytics_pages', '<?php return 0; ?>');
+
+    $edit = array();
+    $edit['googleanalytics_account'] = $ua_code;
+    $this->drupalPost('admin/config/system/googleanalytics', $edit, t('Save configuration'));
+
+    // Compare saved setting with posted setting.
+    $googleanalytics_visibility_pages = variable_get('googleanalytics_visibility_pages', 0);
+    $googleanalytics_pages = variable_get('googleanalytics_pages', $this->randomName(8));
+    $this->assertEqual(2, $googleanalytics_visibility_pages, '[testGoogleAnalyticsPhpFilter]: Pages on which this PHP code returns TRUE is selected.');
+    $this->assertEqual('<?php return 0; ?>', $googleanalytics_pages, '[testGoogleAnalyticsPhpFilter]: PHP code snippet is intact.');
+  }
+
+}

+ 119 - 0
sites/all/modules/contrib/admin/google_analytics/googleanalytics.test.js

@@ -0,0 +1,119 @@
+(function ($) {
+
+/**
+ *  This file is for developers only.
+ *
+ *  This tests are made for the javascript functions used in GA module.
+ *  These tests verify if the return values are properly working.
+ *
+ *  Hopefully this can be added somewhere else once Drupal core has JavaScript
+ *  unit testing integrated.
+ */
+
+"use strict";
+
+Drupal.googleanalytics.test = {};
+
+Drupal.googleanalytics.test.assertSame = function (value1, value2, message) {
+  if (value1 === value2) {
+    console.info(message);
+  }
+  else {
+    console.error(message);
+  }
+};
+
+Drupal.googleanalytics.test.assertNotSame = function (value1, value2, message) {
+  if (value1 !== value2) {
+    console.info(message);
+  }
+  else {
+    console.error(message);
+  }
+};
+
+Drupal.googleanalytics.test.assertTrue = function (value1, message) {
+  if (value1 === true) {
+    console.info(message);
+  }
+  else {
+    console.error(message);
+  }
+};
+
+Drupal.googleanalytics.test.assertFalse = function (value1, message) {
+  if (value1 === false) {
+    console.info(message);
+  }
+  else {
+    console.error(message);
+  }
+};
+
+// Run after the documented is ready or Drupal.settings is undefined.
+$(document).ready(function() {
+
+  /**
+   *  Run javascript tests against the GA module.
+   */
+
+  // JavaScript debugging
+  var base_url = window.location.protocol + '//' + window.location.host;
+  var base_path = window.location.pathname;
+  console.dir(Drupal);
+
+  console.group("Test 'isDownload':");
+  Drupal.googleanalytics.test.assertFalse(Drupal.googleanalytics.isDownload(base_url + Drupal.settings.basePath + 'node/8'), "Verify that '/node/8' url is not detected as file download.");
+  Drupal.googleanalytics.test.assertTrue(Drupal.googleanalytics.isDownload(base_url + Drupal.settings.basePath + 'files/foo1.zip'), "Verify that '/files/foo1.zip' url is detected as a file download.");
+  Drupal.googleanalytics.test.assertTrue(Drupal.googleanalytics.isDownload(base_url + Drupal.settings.basePath + 'files/foo1.zip#foo'), "Verify that '/files/foo1.zip#foo' url is detected as a file download.");
+  Drupal.googleanalytics.test.assertTrue(Drupal.googleanalytics.isDownload(base_url + Drupal.settings.basePath + 'files/foo1.zip?foo=bar'), "Verify that '/files/foo1.zip?foo=bar' url is detected as a file download.");
+  Drupal.googleanalytics.test.assertTrue(Drupal.googleanalytics.isDownload(base_url + Drupal.settings.basePath + 'files/foo1.zip?foo=bar#foo'), "Verify that '/files/foo1.zip?foo=bar#foo' url is detected as a file download.");
+  Drupal.googleanalytics.test.assertFalse(Drupal.googleanalytics.isDownload(base_url + Drupal.settings.basePath + 'files/foo2.ddd'), "Verify that '/files/foo2.ddd' url is not detected as file download.");
+  console.groupEnd();
+
+  console.group("Test 'isInternal':");
+  Drupal.googleanalytics.test.assertTrue(Drupal.googleanalytics.isInternal(base_url + Drupal.settings.basePath + 'node/1'), "Link '" + base_url + Drupal.settings.basePath + "node/2' has been detected as internal link.");
+  Drupal.googleanalytics.test.assertTrue(Drupal.googleanalytics.isInternal(base_url + Drupal.settings.basePath + 'node/1#foo'), "Link '" + base_url + Drupal.settings.basePath + "node/1#foo' has been detected as internal link.");
+  Drupal.googleanalytics.test.assertTrue(Drupal.googleanalytics.isInternal(base_url + Drupal.settings.basePath + 'node/1?foo=bar'), "Link '" + base_url + Drupal.settings.basePath + "node/1?foo=bar' has been detected as internal link.");
+  Drupal.googleanalytics.test.assertTrue(Drupal.googleanalytics.isInternal(base_url + Drupal.settings.basePath + 'node/1?foo=bar#foo'), "Link '" + base_url + Drupal.settings.basePath + "node/1?foo=bar#foo' has been detected as internal link.");
+  Drupal.googleanalytics.test.assertTrue(Drupal.googleanalytics.isInternal(base_url + Drupal.settings.basePath + 'go/foo'), "Link '" + base_url + Drupal.settings.basePath + "go/foo' has been detected as internal link.");
+  Drupal.googleanalytics.test.assertFalse(Drupal.googleanalytics.isInternal('http://example.com/node/3'), "Link 'http://example.com/node/3' has been detected as external link.");
+  console.groupEnd();
+
+  console.group("Test 'isInternalSpecial':");
+  Drupal.googleanalytics.test.assertTrue(Drupal.googleanalytics.isInternalSpecial(base_url + Drupal.settings.basePath + 'go/foo'), "Link '" + base_url + Drupal.settings.basePath + "go/foo' has been detected as special internal link.");
+  Drupal.googleanalytics.test.assertFalse(Drupal.googleanalytics.isInternalSpecial(base_url + Drupal.settings.basePath + 'node/1'), "Link '" + base_url + Drupal.settings.basePath + "node/1' has been detected as special internal link.");
+  console.groupEnd();
+
+  console.group("Test 'getPageUrl':");
+  Drupal.googleanalytics.test.assertSame(base_path, Drupal.googleanalytics.getPageUrl(base_url + Drupal.settings.basePath + 'node/1'), "Absolute internal URL '" +  Drupal.settings.basePath + "node/1' has been extracted from full qualified url '" + base_url + base_path + "'.");
+  Drupal.googleanalytics.test.assertSame(base_path, Drupal.googleanalytics.getPageUrl(Drupal.settings.basePath + 'node/1'), "Absolute internal URL '" +  Drupal.settings.basePath + "node/1' has been extracted from absolute url '" +  base_path + "'.");
+  Drupal.googleanalytics.test.assertSame('http://example.com/node/2', Drupal.googleanalytics.getPageUrl('http://example.com/node/2'), "Full qualified external url 'http://example.com/node/2' has been extracted.");
+  Drupal.googleanalytics.test.assertSame('//example.com/node/2', Drupal.googleanalytics.getPageUrl('//example.com/node/2'), "Full qualified external url '//example.com/node/2' has been extracted.");
+  console.groupEnd();
+
+  console.group("Test 'getDownloadExtension':");
+  Drupal.googleanalytics.test.assertSame('zip', Drupal.googleanalytics.getDownloadExtension(base_url + Drupal.settings.basePath + '/files/foo1.zip'), "Download extension 'zip' has been found in '" + base_url + Drupal.settings.basePath + "files/foo1.zip'.");
+  Drupal.googleanalytics.test.assertSame('zip', Drupal.googleanalytics.getDownloadExtension(base_url + Drupal.settings.basePath + '/files/foo1.zip#foo'), "Download extension 'zip' has been found in '" + base_url + Drupal.settings.basePath + "files/foo1.zip#foo'.");
+  Drupal.googleanalytics.test.assertSame('zip', Drupal.googleanalytics.getDownloadExtension(base_url + Drupal.settings.basePath + '/files/foo1.zip?foo=bar'), "Download extension 'zip' has been found in '" + base_url + Drupal.settings.basePath + "files/foo1.zip?foo=bar'.");
+  Drupal.googleanalytics.test.assertSame('zip', Drupal.googleanalytics.getDownloadExtension(base_url + Drupal.settings.basePath + '/files/foo1.zip?foo=bar#foo'), "Download extension 'zip' has been found in '" + base_url + Drupal.settings.basePath + "files/foo1.zip?foo=bar'.");
+  Drupal.googleanalytics.test.assertSame('', Drupal.googleanalytics.getDownloadExtension(base_url + Drupal.settings.basePath + '/files/foo2.dddd'), "No download extension found in '" + base_url + Drupal.settings.basePath + "files/foo2.dddd'.");
+  console.groupEnd();
+
+  // List of top-level domains: example.com, example.net
+  console.group("Test 'isCrossDomain' (requires cross domain configuration with 'example.com' and 'example.net'):");
+  if (Drupal.settings.googleanalytics.trackCrossDomains) {
+    console.dir(Drupal.settings.googleanalytics.trackCrossDomains);
+    Drupal.googleanalytics.test.assertTrue(Drupal.googleanalytics.isCrossDomain('example.com', Drupal.settings.googleanalytics.trackCrossDomains), "URL 'example.com' has been found in cross domain list.");
+    Drupal.googleanalytics.test.assertTrue(Drupal.googleanalytics.isCrossDomain('example.net', Drupal.settings.googleanalytics.trackCrossDomains), "URL 'example.com' has been found in cross domain list.");
+    Drupal.googleanalytics.test.assertFalse(Drupal.googleanalytics.isCrossDomain('www.example.com', Drupal.settings.googleanalytics.trackCrossDomains), "URL 'www.example.com' not found in cross domain list.");
+    Drupal.googleanalytics.test.assertFalse(Drupal.googleanalytics.isCrossDomain('www.example.net', Drupal.settings.googleanalytics.trackCrossDomains), "URL 'www.example.com' not found in cross domain list.");
+  }
+  else {
+    console.warn('Cross domain tracking is not enabled. Tests skipped.');
+  }
+  console.groupEnd();
+
+});
+
+})(jQuery);

+ 55 - 0
sites/all/modules/contrib/admin/google_analytics/googleanalytics.tokens.inc

@@ -0,0 +1,55 @@
+<?php
+
+/**
+ * @file
+ * Builds placeholder replacement tokens for user-related data.
+ */
+
+/**
+ * Implements hook_token_info().
+ */
+function googleanalytics_token_info() {
+  $user['role-names'] = array(
+    'name' => t('User role names'),
+    'description' => t('The role names the user account is a member of as comma separated list.'),
+    'needs-data' => 'user',
+  );
+  $user['role-ids'] = array(
+    'name' => t('User role ids'),
+    'description' => t('The role ids the user account is a member of as comma separated list.'),
+    'needs-data' => 'user',
+  );
+
+  return array(
+    'tokens' => array('user' => $user),
+  );
+}
+
+/**
+ * Implements hook_tokens().
+ */
+function googleanalytics_tokens($type, $tokens, array $data = array(), array $options = array()) {
+  $sanitize = !empty($options['sanitize']);
+  $replacements = array();
+
+  if ($type == 'user' && !empty($data['user']->roles)) {
+    $account = $data['user'];
+
+    foreach ($tokens as $name => $original) {
+      switch ($name) {
+        // Basic user account information.
+        case 'role-names':
+          $names = implode(',', $account->roles);
+          $replacements[$original] = $sanitize ? check_plain($names) : $names;
+          break;
+
+        case 'role-ids':
+          $ids = implode(',', array_keys($account->roles));
+          $replacements[$original] = $sanitize ? check_plain($ids) : $ids;
+          break;
+      }
+    }
+  }
+
+  return $replacements;
+}

Dosya farkı çok büyük olduğundan ihmal edildi
+ 15 - 0
sites/all/modules/contrib/admin/google_analytics/googleanalytics.variable.inc


+ 27 - 0
sites/all/modules/features/admin/admin.features.user_permission.inc

@@ -220,6 +220,15 @@ function admin_user_default_permissions() {
     'module' => 'menu_admin_per_menu',
     'module' => 'menu_admin_per_menu',
   );
   );
 
 
+  // Exported permission: 'administer google analytics'.
+  $permissions['administer google analytics'] = array(
+    'name' => 'administer google analytics',
+    'roles' => array(
+      'root' => 'root',
+    ),
+    'module' => 'googleanalytics',
+  );
+
   // Exported permission: 'administer imce'.
   // Exported permission: 'administer imce'.
   $permissions['administer imce'] = array(
   $permissions['administer imce'] = array(
     'name' => 'administer imce',
     'name' => 'administer imce',
@@ -626,6 +635,15 @@ function admin_user_default_permissions() {
     'module' => 'pathauto',
     'module' => 'pathauto',
   );
   );
 
 
+  // Exported permission: 'opt-in or out of tracking'.
+  $permissions['opt-in or out of tracking'] = array(
+    'name' => 'opt-in or out of tracking',
+    'roles' => array(
+      'root' => 'root',
+    ),
+    'module' => 'googleanalytics',
+  );
+
   // Exported permission: 'override content type title display'.
   // Exported permission: 'override content type title display'.
   $permissions['override content type title display'] = array(
   $permissions['override content type title display'] = array(
     'name' => 'override content type title display',
     'name' => 'override content type title display',
@@ -732,6 +750,15 @@ function admin_user_default_permissions() {
     'module' => 'translation',
     'module' => 'translation',
   );
   );
 
 
+  // Exported permission: 'use PHP for tracking visibility'.
+  $permissions['use PHP for tracking visibility'] = array(
+    'name' => 'use PHP for tracking visibility',
+    'roles' => array(
+      'root' => 'root',
+    ),
+    'module' => 'googleanalytics',
+  );
+
   // Exported permission: 'use ctools import'.
   // Exported permission: 'use ctools import'.
   $permissions['use ctools import'] = array(
   $permissions['use ctools import'] = array(
     'name' => 'use ctools import',
     'name' => 'use ctools import',

+ 34 - 1
sites/all/modules/features/admin/admin.info

@@ -1,6 +1,7 @@
 name = Admin
 name = Admin
 core = 7.x
 core = 7.x
 package = Gui
 package = Gui
+dependencies[] = admin_menu
 dependencies[] = admin_menu_source
 dependencies[] = admin_menu_source
 dependencies[] = admin_theme
 dependencies[] = admin_theme
 dependencies[] = adminimal_admin_menu
 dependencies[] = adminimal_admin_menu
@@ -22,6 +23,7 @@ dependencies[] = filter_perms
 dependencies[] = footer_message
 dependencies[] = footer_message
 dependencies[] = fpa
 dependencies[] = fpa
 dependencies[] = genpass
 dependencies[] = genpass
+dependencies[] = googleanalytics
 dependencies[] = imce
 dependencies[] = imce
 dependencies[] = linkit
 dependencies[] = linkit
 dependencies[] = login_destination
 dependencies[] = login_destination
@@ -85,6 +87,7 @@ features[user_permission][] = administer contexts
 features[user_permission][] = administer devel menu items
 features[user_permission][] = administer devel menu items
 features[user_permission][] = administer features
 features[user_permission][] = administer features
 features[user_permission][] = administer features menu items
 features[user_permission][] = administer features menu items
+features[user_permission][] = administer google analytics
 features[user_permission][] = administer imce
 features[user_permission][] = administer imce
 features[user_permission][] = administer linkit
 features[user_permission][] = administer linkit
 features[user_permission][] = administer main-menu menu items
 features[user_permission][] = administer main-menu menu items
@@ -130,6 +133,7 @@ features[user_permission][] = menu edit management
 features[user_permission][] = menu edit navigation
 features[user_permission][] = menu edit navigation
 features[user_permission][] = menu edit user-menu
 features[user_permission][] = menu edit user-menu
 features[user_permission][] = notify of path changes
 features[user_permission][] = notify of path changes
+features[user_permission][] = opt-in or out of tracking
 features[user_permission][] = override content type title display
 features[user_permission][] = override content type title display
 features[user_permission][] = participate in workflow
 features[user_permission][] = participate in workflow
 features[user_permission][] = perform backup
 features[user_permission][] = perform backup
@@ -142,6 +146,7 @@ features[user_permission][] = show workflow state form
 features[user_permission][] = switch shortcut sets
 features[user_permission][] = switch shortcut sets
 features[user_permission][] = switch users
 features[user_permission][] = switch users
 features[user_permission][] = translate content
 features[user_permission][] = translate content
+features[user_permission][] = use PHP for tracking visibility
 features[user_permission][] = use ctools import
 features[user_permission][] = use ctools import
 features[user_permission][] = use text format filtred_html
 features[user_permission][] = use text format filtred_html
 features[user_permission][] = view own unpublished content
 features[user_permission][] = view own unpublished content
@@ -167,6 +172,35 @@ features[variable][] = admin_theme_path
 features[variable][] = admin_theme_path_disallow
 features[variable][] = admin_theme_path_disallow
 features[variable][] = admin_toolbar
 features[variable][] = admin_toolbar
 features[variable][] = adminimal_admin_menu_toolbar-disabled
 features[variable][] = adminimal_admin_menu_toolbar-disabled
+features[variable][] = googleanalytics_account
+features[variable][] = googleanalytics_cache
+features[variable][] = googleanalytics_codesnippet_after
+features[variable][] = googleanalytics_codesnippet_before
+features[variable][] = googleanalytics_codesnippet_create
+features[variable][] = googleanalytics_cross_domains
+features[variable][] = googleanalytics_custom
+features[variable][] = googleanalytics_custom_dimension
+features[variable][] = googleanalytics_custom_metric
+features[variable][] = googleanalytics_debug
+features[variable][] = googleanalytics_domain_mode
+features[variable][] = googleanalytics_pages
+features[variable][] = googleanalytics_privacy_donottrack
+features[variable][] = googleanalytics_roles
+features[variable][] = googleanalytics_site_search
+features[variable][] = googleanalytics_trackadsense
+features[variable][] = googleanalytics_trackdoubleclick
+features[variable][] = googleanalytics_tracker_anonymizeip
+features[variable][] = googleanalytics_trackfiles
+features[variable][] = googleanalytics_trackfiles_extensions
+features[variable][] = googleanalytics_tracklinkid
+features[variable][] = googleanalytics_trackmailto
+features[variable][] = googleanalytics_trackmessages
+features[variable][] = googleanalytics_trackoutbound
+features[variable][] = googleanalytics_trackurlfragments
+features[variable][] = googleanalytics_trackuserid
+features[variable][] = googleanalytics_translation_set
+features[variable][] = googleanalytics_visibility_pages
+features[variable][] = googleanalytics_visibility_roles
 features[variable][] = node_admin_theme
 features[variable][] = node_admin_theme
 features[variable][] = theme_adaptivetheme_admin_settings
 features[variable][] = theme_adaptivetheme_admin_settings
 features[variable][] = theme_adaptivetheme_gui_admin_settings
 features[variable][] = theme_adaptivetheme_gui_admin_settings
@@ -182,7 +216,6 @@ features[workflow_access][] = Affichage
 features[wysiwyg][] = filtred_html
 features[wysiwyg][] = filtred_html
 features_exclude[dependencies][menu_editor] = menu_editor
 features_exclude[dependencies][menu_editor] = menu_editor
 features_exclude[dependencies][rules] = rules
 features_exclude[dependencies][rules] = rules
-features_exclude[dependencies][admin_menu] = admin_menu
 features_exclude[dependencies][block] = block
 features_exclude[dependencies][block] = block
 features_exclude[dependencies][menu] = menu
 features_exclude[dependencies][menu] = menu
 features_exclude[dependencies][path] = path
 features_exclude[dependencies][path] = path

+ 217 - 0
sites/all/modules/features/admin/admin.strongarm.inc

@@ -149,6 +149,223 @@ user/*';
   );
   );
   $export['admin_toolbar'] = $strongarm;
   $export['admin_toolbar'] = $strongarm;
 
 
+  $strongarm = new stdClass();
+  $strongarm->disabled = FALSE; /* Edit this to true to make a default strongarm disabled initially */
+  $strongarm->api_version = 1;
+  $strongarm->name = 'googleanalytics_account';
+  $strongarm->value = 'UA-61942434-1';
+  $export['googleanalytics_account'] = $strongarm;
+
+  $strongarm = new stdClass();
+  $strongarm->disabled = FALSE; /* Edit this to true to make a default strongarm disabled initially */
+  $strongarm->api_version = 1;
+  $strongarm->name = 'googleanalytics_cache';
+  $strongarm->value = 0;
+  $export['googleanalytics_cache'] = $strongarm;
+
+  $strongarm = new stdClass();
+  $strongarm->disabled = FALSE; /* Edit this to true to make a default strongarm disabled initially */
+  $strongarm->api_version = 1;
+  $strongarm->name = 'googleanalytics_codesnippet_after';
+  $strongarm->value = '';
+  $export['googleanalytics_codesnippet_after'] = $strongarm;
+
+  $strongarm = new stdClass();
+  $strongarm->disabled = FALSE; /* Edit this to true to make a default strongarm disabled initially */
+  $strongarm->api_version = 1;
+  $strongarm->name = 'googleanalytics_codesnippet_before';
+  $strongarm->value = '';
+  $export['googleanalytics_codesnippet_before'] = $strongarm;
+
+  $strongarm = new stdClass();
+  $strongarm->disabled = FALSE; /* Edit this to true to make a default strongarm disabled initially */
+  $strongarm->api_version = 1;
+  $strongarm->name = 'googleanalytics_codesnippet_create';
+  $strongarm->value = array();
+  $export['googleanalytics_codesnippet_create'] = $strongarm;
+
+  $strongarm = new stdClass();
+  $strongarm->disabled = FALSE; /* Edit this to true to make a default strongarm disabled initially */
+  $strongarm->api_version = 1;
+  $strongarm->name = 'googleanalytics_cross_domains';
+  $strongarm->value = '';
+  $export['googleanalytics_cross_domains'] = $strongarm;
+
+  $strongarm = new stdClass();
+  $strongarm->disabled = FALSE; /* Edit this to true to make a default strongarm disabled initially */
+  $strongarm->api_version = 1;
+  $strongarm->name = 'googleanalytics_custom';
+  $strongarm->value = '0';
+  $export['googleanalytics_custom'] = $strongarm;
+
+  $strongarm = new stdClass();
+  $strongarm->disabled = FALSE; /* Edit this to true to make a default strongarm disabled initially */
+  $strongarm->api_version = 1;
+  $strongarm->name = 'googleanalytics_custom_dimension';
+  $strongarm->value = array();
+  $export['googleanalytics_custom_dimension'] = $strongarm;
+
+  $strongarm = new stdClass();
+  $strongarm->disabled = FALSE; /* Edit this to true to make a default strongarm disabled initially */
+  $strongarm->api_version = 1;
+  $strongarm->name = 'googleanalytics_custom_metric';
+  $strongarm->value = array();
+  $export['googleanalytics_custom_metric'] = $strongarm;
+
+  $strongarm = new stdClass();
+  $strongarm->disabled = FALSE; /* Edit this to true to make a default strongarm disabled initially */
+  $strongarm->api_version = 1;
+  $strongarm->name = 'googleanalytics_debug';
+  $strongarm->value = 0;
+  $export['googleanalytics_debug'] = $strongarm;
+
+  $strongarm = new stdClass();
+  $strongarm->disabled = FALSE; /* Edit this to true to make a default strongarm disabled initially */
+  $strongarm->api_version = 1;
+  $strongarm->name = 'googleanalytics_domain_mode';
+  $strongarm->value = '1';
+  $export['googleanalytics_domain_mode'] = $strongarm;
+
+  $strongarm = new stdClass();
+  $strongarm->disabled = FALSE; /* Edit this to true to make a default strongarm disabled initially */
+  $strongarm->api_version = 1;
+  $strongarm->name = 'googleanalytics_pages';
+  $strongarm->value = 'admin
+admin/*
+batch
+node/add*
+node/*/*
+user/*/*';
+  $export['googleanalytics_pages'] = $strongarm;
+
+  $strongarm = new stdClass();
+  $strongarm->disabled = FALSE; /* Edit this to true to make a default strongarm disabled initially */
+  $strongarm->api_version = 1;
+  $strongarm->name = 'googleanalytics_privacy_donottrack';
+  $strongarm->value = 1;
+  $export['googleanalytics_privacy_donottrack'] = $strongarm;
+
+  $strongarm = new stdClass();
+  $strongarm->disabled = FALSE; /* Edit this to true to make a default strongarm disabled initially */
+  $strongarm->api_version = 1;
+  $strongarm->name = 'googleanalytics_roles';
+  $strongarm->value = array(
+    1 => 0,
+    2 => 0,
+    3 => 0,
+    4 => 0,
+  );
+  $export['googleanalytics_roles'] = $strongarm;
+
+  $strongarm = new stdClass();
+  $strongarm->disabled = FALSE; /* Edit this to true to make a default strongarm disabled initially */
+  $strongarm->api_version = 1;
+  $strongarm->name = 'googleanalytics_site_search';
+  $strongarm->value = FALSE;
+  $export['googleanalytics_site_search'] = $strongarm;
+
+  $strongarm = new stdClass();
+  $strongarm->disabled = FALSE; /* Edit this to true to make a default strongarm disabled initially */
+  $strongarm->api_version = 1;
+  $strongarm->name = 'googleanalytics_trackadsense';
+  $strongarm->value = 0;
+  $export['googleanalytics_trackadsense'] = $strongarm;
+
+  $strongarm = new stdClass();
+  $strongarm->disabled = FALSE; /* Edit this to true to make a default strongarm disabled initially */
+  $strongarm->api_version = 1;
+  $strongarm->name = 'googleanalytics_trackdoubleclick';
+  $strongarm->value = 0;
+  $export['googleanalytics_trackdoubleclick'] = $strongarm;
+
+  $strongarm = new stdClass();
+  $strongarm->disabled = FALSE; /* Edit this to true to make a default strongarm disabled initially */
+  $strongarm->api_version = 1;
+  $strongarm->name = 'googleanalytics_tracker_anonymizeip';
+  $strongarm->value = 1;
+  $export['googleanalytics_tracker_anonymizeip'] = $strongarm;
+
+  $strongarm = new stdClass();
+  $strongarm->disabled = FALSE; /* Edit this to true to make a default strongarm disabled initially */
+  $strongarm->api_version = 1;
+  $strongarm->name = 'googleanalytics_trackfiles';
+  $strongarm->value = 1;
+  $export['googleanalytics_trackfiles'] = $strongarm;
+
+  $strongarm = new stdClass();
+  $strongarm->disabled = FALSE; /* Edit this to true to make a default strongarm disabled initially */
+  $strongarm->api_version = 1;
+  $strongarm->name = 'googleanalytics_trackfiles_extensions';
+  $strongarm->value = '7z|aac|arc|arj|asf|asx|avi|bin|csv|doc(x|m)?|dot(x|m)?|exe|flv|gif|gz|gzip|hqx|jar|jpe?g|js|mp(2|3|4|e?g)|mov(ie)?|msi|msp|pdf|phps|png|ppt(x|m)?|pot(x|m)?|pps(x|m)?|ppam|sld(x|m)?|thmx|qtm?|ra(m|r)?|sea|sit|tar|tgz|torrent|txt|wav|wma|wmv|wpd|xls(x|m|b)?|xlt(x|m)|xlam|xml|z|zip';
+  $export['googleanalytics_trackfiles_extensions'] = $strongarm;
+
+  $strongarm = new stdClass();
+  $strongarm->disabled = FALSE; /* Edit this to true to make a default strongarm disabled initially */
+  $strongarm->api_version = 1;
+  $strongarm->name = 'googleanalytics_tracklinkid';
+  $strongarm->value = 0;
+  $export['googleanalytics_tracklinkid'] = $strongarm;
+
+  $strongarm = new stdClass();
+  $strongarm->disabled = FALSE; /* Edit this to true to make a default strongarm disabled initially */
+  $strongarm->api_version = 1;
+  $strongarm->name = 'googleanalytics_trackmailto';
+  $strongarm->value = 1;
+  $export['googleanalytics_trackmailto'] = $strongarm;
+
+  $strongarm = new stdClass();
+  $strongarm->disabled = FALSE; /* Edit this to true to make a default strongarm disabled initially */
+  $strongarm->api_version = 1;
+  $strongarm->name = 'googleanalytics_trackmessages';
+  $strongarm->value = array(
+    'status' => 0,
+    'warning' => 0,
+    'error' => 0,
+  );
+  $export['googleanalytics_trackmessages'] = $strongarm;
+
+  $strongarm = new stdClass();
+  $strongarm->disabled = FALSE; /* Edit this to true to make a default strongarm disabled initially */
+  $strongarm->api_version = 1;
+  $strongarm->name = 'googleanalytics_trackoutbound';
+  $strongarm->value = 1;
+  $export['googleanalytics_trackoutbound'] = $strongarm;
+
+  $strongarm = new stdClass();
+  $strongarm->disabled = FALSE; /* Edit this to true to make a default strongarm disabled initially */
+  $strongarm->api_version = 1;
+  $strongarm->name = 'googleanalytics_trackurlfragments';
+  $strongarm->value = 0;
+  $export['googleanalytics_trackurlfragments'] = $strongarm;
+
+  $strongarm = new stdClass();
+  $strongarm->disabled = FALSE; /* Edit this to true to make a default strongarm disabled initially */
+  $strongarm->api_version = 1;
+  $strongarm->name = 'googleanalytics_trackuserid';
+  $strongarm->value = 0;
+  $export['googleanalytics_trackuserid'] = $strongarm;
+
+  $strongarm = new stdClass();
+  $strongarm->disabled = FALSE; /* Edit this to true to make a default strongarm disabled initially */
+  $strongarm->api_version = 1;
+  $strongarm->name = 'googleanalytics_translation_set';
+  $strongarm->value = 0;
+  $export['googleanalytics_translation_set'] = $strongarm;
+
+  $strongarm = new stdClass();
+  $strongarm->disabled = FALSE; /* Edit this to true to make a default strongarm disabled initially */
+  $strongarm->api_version = 1;
+  $strongarm->name = 'googleanalytics_visibility_pages';
+  $strongarm->value = '0';
+  $export['googleanalytics_visibility_pages'] = $strongarm;
+
+  $strongarm = new stdClass();
+  $strongarm->disabled = FALSE; /* Edit this to true to make a default strongarm disabled initially */
+  $strongarm->api_version = 1;
+  $strongarm->name = 'googleanalytics_visibility_roles';
+  $strongarm->value = '0';
+  $export['googleanalytics_visibility_roles'] = $strongarm;
+
   $strongarm = new stdClass();
   $strongarm = new stdClass();
   $strongarm->disabled = FALSE; /* Edit this to true to make a default strongarm disabled initially */
   $strongarm->disabled = FALSE; /* Edit this to true to make a default strongarm disabled initially */
   $strongarm->api_version = 1;
   $strongarm->api_version = 1;

Bu fark içinde çok fazla dosya değişikliği olduğu için bazı dosyalar gösterilmiyor