title: How to send a ga command to a tracker with no name?
body: <p>We have a custom Google Analytics plugin that will be sending commands to track custom pageviews and log events. Here's a simplified repro of our scenario:</p>
  
  <pre><code>// Version 1: only works with analytics.js, not with GTM
  
  function GaPlugin(tracker, config) {
      // Simplified for SO, we actually use the config argument
      // to track more interesting pages and events...
      ga(tracker.get('name') + ".send", "pageview", "/virtual/page/view");
  }
  
  var ga = window[window["GoogleAnalyticsObject"] || "ga"];
  
  if (typeof ga == "function") {
      ga("provide", "myAnalytics", GaPlugin);
      ga("require", "myAnalytics", { /* omitted for simplicity */ });
  }
  </code></pre>
  
  <p>This works fine if <code>analytics.js</code> is included directly on the page. However, we're now including universal analytics on the page using the Google Tag Manager. Thus we ran into the dreaded error...</p>
  
  <blockquote>
    <p>Command ignored. Unknown target: undefined</p>
  </blockquote>
  
  <p>...as seen in the Google Analytics debugging Chrome plugin when the <code>require</code> command is being executed.</p>
  
  <p><a href="https://stackoverflow.com/q/28765806/419956">This question</a> and <a href="http://www.statstory.com/command-ignored-unknown-target-undefined/" rel="nofollow noreferrer">this blogpost</a> imply the need to set a tracker name (in GTM, using: Edit Tag => More Settings => Advanced Configuration => Set Tracker Name checkbox) but the tooltip says "<em>Use of named trackers is highly discouraged in GTM</em>". So instead I changed things to this:</p>
  
  <pre><code>// Version 2: crashes with GTM because ga is loaded after this code
  
  function GaPlugin(tracker, config) {
      // Simplified for SO, we actually use the config argument
      // to track more interesting pages and events...
      ga(tracker.get('name') + ".send", "pageview", "/virtual/page/view");
  }
  
  var ga = window[window["GoogleAnalyticsObject"] || "ga"];
  
  if (typeof ga == "function") {
      ga("provide", "myAnalytics", GaPlugin);
      ga(ga.getAll()[0].get("name") + ".require", "myAnalytics", { });
  }
  </code></pre>
  
  <p>But now I'm met with an error because <code>ga</code> is <code>undefined</code> when the above executes, because GTM will load universal analytics asynchronously, where I want to run my code to bootstrap the plugin right away. This also means I cannot place a callback on the <code>ga</code> command queue, because again: it doesn't exist yet.</p>
  
  <p>In essence, the order of things (I think) is now:</p>
  
  <ol>
  <li>The GTM snippet starts loading (async).</li>
  <li>My own javascript code runs.</li>
  <li>GTM will start loading analytics (async).</li>
  <li>Analytics is loaded and ready to be used.</li>
  </ol>
  
  <p>The only workaround I could think of was this:</p>
  
  <pre><code>// Version 3: ugly workaround...
  
  function GaPlugin(tracker, config) {
      // Simplified for SO, we actually use the config argument
      // to track more interesting pages and events...
      ga(tracker.get('name') + ".send", "pageview", "/virtual/page/view");
  }
  
  var interval = setInterval(function() {
      var ga = window[window["GoogleAnalyticsObject"] || "ga"];
  
      if (typeof ga == "function" &amp;&amp; typeof ga.getAll == "function") {
          ga("provide", "myAnalytics", GaPlugin);
          ga(ga.getAll()[0].get("name") + ".require", "myAnalytics", { });
          clearInterval(interval);
      }
  }, 250);
  </code></pre>
  
  <p><strong>Isn't there a better way to do this?</strong> The GTM documentation nor the GA Plugins documentation seems to have any info on this.</p>
  
  <hr>
  
  <p>As a footnote, I just realized it might also work if I mimic <a href="https://developers.google.com/analytics/devguides/collection/analyticsjs/tracking-snippet-reference" rel="nofollow noreferrer">the tracking snippet</a> by creating <code>ga</code> as a command queue myself. But that also feels like a workaround, not a solution...</p>