Shiny Developer Series Webinar Discussion - Episode 3 - Mark Edmondson on googleAnalyticsR and linking Shiny to complex APIs

Follow-up questions from the shiny developer series.

For recordings of the webinar, go to the Shiny Deverloper Series website at shinydevseries.com. For this webinar's recording visit shinydevseries.com/ep3.


Mark Edmondson on googleAnalyticsR and linking Shiny to complex APIs

Held on Friday, June 21 from Noon - 1:00 pm Eastern Time

This episode showcases how Shiny - like R itself - can be integrated nicely with intricate APIs, giving Shiny app developers a wealth of additional functionality. Mark’s googleAnalyticsR package is a great example of this.

Mark Edmondson - Data Scientist at IIH Nordic, working extensively to integrate Google Analytics and other digital marketing tools into data science products. Mark's Website - Code - Twitter.


Webinar questions:

Working with APIs

RB: if i had to inspect where the api call was being made where in the package would i need to look? the idea being that if i had to create a package for another api with oauth i wanted some inspiration

CK: Can you advize on best practices for handling api errors? For example, I've deployed a shiny app built upon a google API, but how should I handle api errors that occur in future in production?

AJ: How do you advice creating user authentication for accessing a plumber API for Excel VBA for example on RStudio Connect

Teach us, Mark

DH: Can Mark publish a list of his "top" packages like memoise (I think pronounce "memwah")?

MI: Mark please, where did you learn to create packages in such a short period of time? (and thank you very much for the presentation)

RL: What from Mark point of view the best way to grow from a know nothing shinny to a good enough developer - any trick he would have? Thanks

How can we help?

IT: I would like to thank Mark for his excellent work! And would like to know about the slack channel and how we could participate? (context: Mark mentioned that an increasing part of his R-package development time is spent on non-coding tasks, and he relies on a community of package sustainers to help, mostly coordinated on github and slack)

3 Likes

First of all thank you very much for having me on the webinar, it was fun :slight_smile:

The first place to look would be the httr vignette "Best practices for API packages" which has lots of examples including those using OAuth2. For googleAuthR packages the function factory used by all of them all starts with the gar_api_generator() which adds looking for tokens in Shiny environments, batching and caching. The most modern take is gargle by Jenny Bryan which is under development now.

Covered in the webinar, but my first reaction is that you want to surface errors as quickly as possible, so would want them to be live even in production. If you want to mask transitory errors though then you can use tryCatch() or the equivalent to return a NULL response upon error, which will invalidate the shiny::reactive() object the API call should be wrapped in, so as you can then use shiny::req() or shiny::validate() to create custom error messages.

I've never done similar so can't speak from experience, perhaps RStudio Connect has someway you can do this, if not then my first approach would be to use Google Cloud Endpoints which gives you a API proxy to add API keys, caching and authentication, a demo of which I have here that uses Google App Engine Flexible and plumber.

I'm so embarrassed at my pronunciation of memoise on the webinar. :wink:

If we're talking packages for API packages in particular, my R package stack always includes:

  • httr - the godfather of R APIs
  • jsonlite - turning R inputs into JSON and back again
  • pkgdown - documentation
  • memoise - caching responses
  • assertthat - defensive programming and checking of inputs

Then depending on how hard it is to parse the response, and how user friendly you want to make the final output you could choose to add some packages to parse the responses such as purrr or dplyr

For my first package searchConsoleR I read Hadley Wickham's R package book cover to cover, adding the elements to the package as I went.

After that I used the Google Discovery API service integration of googleAuthR via the gar_create_package() function to generate the functions and objects, then added functions to parse those into user-friendly functions, and add lots of documentation. But I don't make any packages at the moment as its enough time maintaining the existing ones.

The documentation on the Shiny website I still reference a lot and think are excellent.

I have a post on this forum about my approach to Shiny development that may be helpful.

Other than that I'd say having a good iterative workflow to keep testing each change you do, making sure to not do too much with each reactive object, and get the server side working well first with a basic UI first before making it look pretty.

The Slack channel #googleAuthRverse has a signup form here - that and any GitHub issues/pull requests are highly appreciated! :slight_smile:

4 Likes

nice episode....

Just a question.

Should I use tryCatch inside a reactive.
Is it the right thing to do?
Does it impact speed...

Please any suggestion would do

1 Like

I think this is a great question, and something I'd love to hear from the R-Shiny community about in terms of their best practices for error handling.

In the episode, Mark talked about working with tryCatch. But also I know also the shiny team wrote this article on error handling with shiny that might be valuable:

Write error messages for your UI with validate - Have you ever seen a Shiny app go wrong? Shiny delivers a bold red error message to your user. This message is often unhelpful because it mentions things that you may understand as a developer, but that your user may not.

1 Like

Thanks for replying this is exactly my point . Shiny already has a validate function so should I use tryCatch for error handling as well. When should I use it and will that impact the speed.

Apart from validate. I was asking more of a general question. Please do reply if you have any suggestions on it.

With APIs you have to expect them to fail, which is why its best to put the calls in their own reactive object e.g.

api_data <- reactive({
  call_api(blah)
})

plot_data <- renderPlot({
  plot(api_data())
})

If the API returns an error it may surface that error message in your Shiny app (red text) before it hits any validate() so I tend to use the tryCatch() to log the error but also make sure the reactive object returns NULL , so that the validate() (or req()) will trigger due to being invalidated by the NULL.

e.g.

api_data <- reactive({

  tryCatch(call_api(blah), 
           error = function(err){
             message(paste("WARK WARK ERROR", err$message))
             NULL 
           })
  })

plot_data <- renderPlot({
  validate(
    need(api_data, "The API call failed") 
    )

  plot(api_data())

})
1 Like

Thanks a lot for explaining

1 Like

This topic was automatically closed 54 days after the last reply. New replies are no longer allowed.