Using URLs and Query Parameters

Background on the URL

In Looker pre-3.18, the url is a long list of parameters which includes the fields, filters, filter values, pivots, row limits, column limits, total settings, row total settings, and sorts.

In Looker 3.18 and later the url is hashed and stored in a slug, which is used to generate the query. No matter the version, the following parameters can be used to generate queries.

Parameters and How to Use Them

Important: Any field in the pivots or sorts list must also reside in the fields list.

A general url with all of the parameters:


https://company.looker.com/explore/model/explore_name?fields=view.field_1,view.field_2,view.count
&f[view.filter_1_dimension]={{ value }}
&f[view.filter_2_on_date]=last+60+days
&pivots=view.field_2
&limit=50
&column_limit=20
&total=true
&row_total=right
&sorts=view.field_1,view.count+desc

Explanations for each parameter:

  • fields: The list of fields used. You may also use a set from a view as such fields=view_name.set_name*
  • f[]: Declaration of a filter with it’s respective value. Any additional filter is declared with another f[view.dimension_name]
  • pivots: The set of dimensions you want to pivot in the look.
  • limit: The limit for the query. Any value > 5000 will default to 5000.
  • column_limit: The column limit. This only exists if there is at least one pivoted dimension.
  • total: Column totals toggle. The value for this is either true or false (off or on, respectively).
  • row_total: Row total toggle. The value for this is either true or false (off or on, respectively).
  • sorts: The fields to sort on. Default or no value entered is ascending sort.

Note (October 2017):

The code above this post is obsolete, as we now allow folks to reference the current filters placed on a given dimension or measure and pass them along in the HTML, which works great for passing filters between dashboards.

The code looks like this: _filters[‘field_name’]

For example:

dimension: company {
  type: string
  sql: ${TABLE}.company

link: {
label: “Activity Overview”
url: “/dashboards/123?Date={{ _filters[‘user.created_at’] | url_encode }}”
}
}

4 25 15.3K
25 REPLIES 25

Super cool! Do you know how one would add a semi-variable filter?

For example, say I want to filter on something occurring in the past 90 days. The filter will be less variable than a { { value } }, but a date that qualifies as in the “past 90 days” is certainly not going to be fixed.

If I create a Look and take a look at the filters, I see what appear to be key-value pairs for today’s date (represented as 2015-04-07) and a 90 day offset. Sure, I could bake this into my URL, but it’ll give me the wrong data for any day other than today.

Know how to solve this?

Hey Cutler!

The way to input values such as ‘past 90 days’ into a filter is by simply replacing {{ value }} in the example above with ‘past+90+days’. Essentially, you may enter a string value for a filter keeping in mind to replace spaces with '+'s. The example url would be:

https://company.looker.com/explore/model/explore_name?fields=view.field_1&f[view.filter_1_dimension]=last+90+days

Hey team,

How do I use the html tags to carry over a filter to my linked URL? I’m writing something that looks like this:
/explore/production/order?fields=cpt_metrics.cpt_code&f[order.completed_date]={{ value }}

The {{ value }} is pulling the value of the cell (which is a measure) but I want to pull the value of the filter on the source query. Basically, I want to do exactly what Zach responded above, except I want the ‘last 90 days’ to be configurable by the user in that source query. Any way to do this?

Hey @Leland_Robbins, there isn’t currently a straightforward way to do this, but I’ve added you to the feature request for it.

However, you might be able to do this with some fancy liquid templating. Fair warning, this code is completely absurd, and a real developer would probably laugh hysterically at me 😄. However, this seemed to work in the situation I tested:

html: |
  {% assign url_split_at_f = link | split: '&f' %}
  {% assign user_filters = '' %}
  {% assign continue_loop = true %}

  {% for url_part in url_split_at_f offset:1 %}
    {% if continue_loop %}
      {% if url_part contains '&sorts' %}
        {% assign part_split_at_sorts = url_part | split: '&sorts' %}
        {% assign last_filter = part_split_at_sorts | first %}
        {% assign user_filters = user_filters | append:'&f' %}
        {% assign user_filters = user_filters | append:last_filter %}
        {% assign continue_loop = false %}
      {% else %}
        {% assign user_filters = user_filters | append:'&f' %}
        {% assign user_filters = user_filters | append:url_part %}
      {% endif %}
    {% endif %}
  {% endfor %}

  <a href="http://whatever?{{ user_filters }}">My Link</a>

Liquid just has limited string parsing abilities, which makes this clunky. I wish it had a find or search type of function.

In any case, essentially what I’m doing here is using the {{ link }} value, which is the link Looker normally generates for drilling. Then I am parsing that URL for the filters that the user has added.

Unfortunately this will only work if the user changes a filter and also runs the query. If they don’t run the query the value that they change to will not dynamically be reflected in the URL I’m building.

MikeD
Participant II

Just a note on this… I had a value with embedded characters so the generated url wouldn’t work. I needed to do this…

<a href="/dashboards/ecommerce/category_lookup?category={{ value | url_encode | replace: '&','%26' }}

…to get a value url.

Hey All:

Is there a solution to @Leland_Robbins request? I need the same functionality now (pulling the value of the filters into the HTML tag), and since the original question was in August, I was hoping it would be a feature by now.

Thanks!

@ArvindR It is not yet possible, but a recent discussion with eng notes that this should be achievable in todays world. No eta on priority/timing of the feature but we’ll keep you all posted.

+1 for adding it as a feature. Would be so helpful to piece together a number of different looks on the same dashboard via a specific filter.

+1 on getting it as a feature.

@Zam Has anything in the latest releases solved this? It seems like the new links functionality might provide the answer but I haven’t had success hacking anything together yet.

@Leland_Robbins Grabbing filters is in fact possible now since drill_fields: is allowed on dimensions. We’re working on expanding the below approach to be used in links but for now it’s only available via html:

- dimension: some_field
  type: string
  sql: ${TABLE}.some_thing
  drill_fields: [field_1, field_2, field_3, or_a_drill_field_set]
  html: |
    <a href="{{ link }}">{{ value }}</a>

The above will use the drill fields in addition to the current filters.

Hey @Zam! So currently I am using the above {{ link }} construction to carry filters over to a new explore, like so:

  - dimension: number_of_events_between
    label: 'Number of Events from Event 1 to Event 2'
    type: number
    sql: ${TABLE}.number_of_events
    html: |
      <a href="https://looker.counsyl.com/explore/production/timeline_sankey?timeline_sankey.source,timeline_sankey.target,claim.count{{ link }}">{{ value }}
        <img src="https://cdn1.iconfinder.com/data/icons/the-data-visualisation-catalogue-set-i/130/sankey_diagram-20.png"></a>  

This successfully carries over the filters from the original query (to my surprise, since I thought {{ link }} would just write out the full URL). However, the fields that I’ve tried to tack on here,

timeline_sankey.source,timeline_sankey.target,claim.count

don’t make it to the drill-down query. These fields don’t exist in the old explore, which is why I’ve tried to force them into the drill-down query here. Is there any way to successfully carry new fields or filters in combination with filters from the original query in a similar manner to what I am trying above?

@calbanese It sounds like you want to retain filters while moving to a new explore, if this is correct then it’s going to take some url munging to get there. I’d recommend returning {{ link }} by itself to get an idea of how the url returned looks, then from their add appropriate fields, swap out the explore, and voila!

Way easier said than done, but liquid should be able to parse and replace (similar to how Brett did in his above comment).

@Zam, How are the URL hashes generated? It could be useful to generate the hash ourselves (via liquid) and pass it as a slug in the html for a field (e.g. to shorten what might otherwise be a too-long URL in the case of many many filter values). Can you provide a Liquid snippet showing how to do it?

@Tom_Russell there isn’t a supported way to do it, but we may be able to come up with a workaround via the api. Will be messaging you via support@ since some of the information required in the workaround may be sensitive to your business.

Does {{ link }} work any longer? I am getting variable not found ‘link’ errors when I try to carry current explore filters through to a linked explore via urls.

@Leland_Robbins {{ link }} should still work as usual! If you’re seeing errors, would you visit help.looker.com with URLs to the page that generates the error message and we can troubleshoot from there?

yuriy
Participant II

Hey team!
It was so nice seeing everyone in person on the conference.

Can i use url parameters with API to get json formatted data?
I only see that you can run a look by look id, in the API.

Thank you

Hey there! Glad you had a good time at Join 2016 @yuriy 🙂

You can pass query parameters using the run_inline_query endpoint, which supplies several arguments such as view, filters, limit, etc. to change the parameters of a query on the fly through the API. However, these won’t be based on any particular Look, but rather are run against the Explore name you specify in view.

You can find more info about this endpoint here: https://looker.com/docs/reference/api-and-integration/api-reference/query#run_inline_query

An updated version of the html is below.

Please note that dimension links no longer contain filter values. The following code should work as-is for measures, but for dimensions, you’ll need to just grab a measure link as opposed to the dimension link. For example, you can replace {% assign url_split_at_f = link | split: 'f[' %} with {% assign url_split_at_f = count._link | split: 'f[' %}. Also note that any measure you reference this way must have a drill_fields parameter for a link to be generated.

{% assign url_split_at_f = link | split: 'f[' %}
          {% assign user_filters = link | truncate: 0 | replace: '...','' %}
          {% assign continue_loop = link == true %}
          {% for url_part in url_split_at_f offset:1 %}
            {% if continue_loop %}
              {% if url_part contains 'sorts' %}
                {% assign part_split_at_sorts = url_part | split: 'sorts' %}
                {% assign last_filter = part_split_at_sorts | first %}
                {% assign user_filters = user_filters | append:'f[' %}
                {% assign user_filters = user_filters | append:last_filter %}
                {% assign continue_loop = link == false %}
              {% else %}
                {% assign user_filters = user_filters | append:'f[' %}
                {% assign user_filters = user_filters | append:url_part %}
              {% endif %}
            {% endif %}
          {% endfor %}

          {% assign remove_last_ampersand = user_filters.size | plus: 2 %}
          {% assign user_filters = user_filters | truncate: remove_last_ampersand  %}
          {% assign user_filters = user_filters | remove: '...' %}
          {% assign user_filters = user_filters | replace: 'f[orders.created_date]', 'Date' %}
          {% assign user_filters = user_filters | replace: 'f[products.brand_name]', 'Brand' %}
          {% assign user_filter_split = user_filters | split: '&' %}
          {% for filter in user_filter_split %}
            {% assign filter_with_amp = filter | append: '&' %}
            {% if filter_with_amp contains 'f['%}
              {% assign user_filters = user_filters | remove: filter_with_amp %}
            {% endif %}
          {% endfor %}
          {{user_filters}}

The code above this post is obsolete, as we now allow folks to reference the current filters placed on a given dimension or measure and pass them along in the HTML, which works great for passing filters between dashboards.

The code looks like this: _filters[‘field_name’]

For example:

dimension: company {
  type: string
  sql: ${TABLE}.company

  link: {
    label: "Activity Overview"
    url: "/dashboards/123?Date={{ _filters['user.created_at'] | url_encode }}"
  }
}

What Permission Set is required for viewing these field links? It’s not explicitly called out as ‘explore’, but I believe that may be the case.

It’s actually a “see_drill_overlay” action that is automatically checked off when you include ‘explore’, but is not in ‘explore’'s sub-tree.

@maxcorbin Is it possible to use the link parameter in a model and pass a filter from a dashboard, which is based on a field from another model? I have tried a lot of different modifications to the URL but it doesn’t seem to pass the values of the filter which is based on another model.

Can you please show output results as image as well so that new learners can easily understood

Top Labels in this Space
Top Solution Authors