Search code examples
xsltgoogle-analyticsamp-html

Reuse a set of XSLT conditions for different output (in this case amp-analytics configuration)


This is a hellish combination of technologies, but I have no choice. I need to output an amp-analytics configuration object on an AMP HTML page that gets rendered with XSLT. The docs for configuration are here just in case.

Look at this part of the configuration. You need to output a key in "vars" attribute for each of the variables you need to send to analytics. But you also need to include their names in a request query string. There can be several requests.

{
  "requests": {
    "pageview": "https://example.com/analytics?url=${canonicalUrl}&title=${title}&acct=${account}&clientId=${clientId(cid-scope)}",
  },
  "vars": {
    "account": "ABC123",
    "title": "Homepage"
  }
}

I have an XML list of the variables:

<vars>
    <account>111</account>
    <title>222</title>
    <foo>333</foo>
</vars>

In my XSLT I go like that:

<xsl:if test="/vars/account">
    "account": "<xsl:value-of select="/vars/account" />",
</xsl:if>
<xsl:if test="/vars/title">
    "title": "<xsl:value-of select="/vars/title" />",
</xsl:if>
<xsl:if test="/vars/foo">
    "foo": "<xsl:value-of select="/vars/foo" />",
</xsl:if>

Okay, that's ugly but fine. But now I have to explicitly include all these variables in every request in requests attribute like &amp;title=${title}&amp;acct=${account}&amp;cd1=${foo}. Here I get lost.

I don't want to duplicate all the logic for outputting a query string. The only thing I came up is to make a named template with a parameter and call it for each request:

<xsl:template name="vars">
    <xsl:param name="for_query" select="1"/>    
    <xsl:if test="/vars/account">
        <xsl:choose>
            <xsl:when test="$for_query = 1">&amp;account=${account}</xsl:when>
            <xsl:otherwise>"account": "<xsl:value-of select="/vars/account" />",</xsl:otherwise>
        </xsl:choose>
    </xsl:if>
    <xsl:if test="/vars/title">
        <xsl:choose>
            <xsl:when test="$for_query = 1">&amp;title=${title}</xsl:when>
            <xsl:otherwise>"title": "<xsl:value-of select="/vars/title" />",</xsl:otherwise>
        </xsl:choose>
    </xsl:if>
    <xsl:if test="/vars/foo">
        <xsl:choose>
            <xsl:when test="$for_query = 1">&amp;foo=${foo}</xsl:when>
            <xsl:otherwise>"foo": "<xsl:value-of select="/vars/foo" />",</xsl:otherwise>
        </xsl:choose>
    </xsl:if>
</xsl:template>

Imagine this a few times longer and a tad more sophisticated and you'll be no wonder why it makes my eyes bleed. Then i call it where appropriate:

{
  "requests": {
    "pageview": "https://example.com/analytics?url=${canonicalUrl}<xsl:call-template name="vars" />",
    "event": "https://example.com/analytics?url=${canonicalUrl}<xsl:call-template name="vars" />"
  },
  "vars": {
    <xsl:call-template name="vars">
        <xsl:with-param name="for_query" select="0"/>
    </xsl:call-template>
    "look_ma": "no_comma"
  }
}

Any less barbaric solutions you'd recommend?


Solution

  • Have you tried using extraUrlParams? They should let you specify params without touching the request and vars block.

    https://github.com/ampproject/amphtml/blob/master/extensions/amp-analytics/amp-analytics.md#extra-url-params