ggiraph: making ggplot2 graphics answer the mouse
make 'ggplot' graphics interactive
At a glance
- What is it?
- ggiraph is an R package that adds tooltips, hover effects and JavaScript actions to ggplot2 output by exporting it as an SVG document with attributes attached to elements, and it exposes selections back to Shiny as reactive values. The R package is distributed on CRAN, and the interactive layer is a d3 based JavaScript module built with webpack.
- Who is it for?
- Use ggiraph when your ggplot2 output has to be a web graphic rather than a static image, either because a reader needs a tooltip on a point or because a Shiny application needs the selected ids back on the server, since the SVG export with attached attributes is the only mechanism on offer. Do not expect it to work for other graphics engines, since the entire package is built around ggplot2 layers and their interactive twins.
- Can I use it commercially?
- Not without permission. GitHub finds no licence file in the repository, and without a licence all rights are reserved by default: you may read the code but not reuse it. Check the README, or ask the authors, before using it.
- Is it still maintained?
- Yes. The repository last received commits 9 days ago.
- What is it written in?
- Mainly R, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 24, 2026, and from our analysis. They are not legal advice.
Editorial analysis
Interactivity arrives as three new aesthetics
The package adds interactivity to ggplot geometries, legends and theme elements through three aesthetics you set inside aes(). The tooltip aesthetic controls what appears when the mouse is over an element. The onclick aesthetic is a JavaScript function executed when the element is clicked, which is how you open a hyperlink from a plot. The data_id aesthetic attaches an identifier to elements, and it is the one that carries meaning: it is what hover and click actions key on, and it is what a Shiny application later receives. The design keeps the interactive surface inside the grammar you already know rather than adding a parallel API, but the cost is that a layer is not interactive until at least one of those three aesthetics is present.
Swap the geom, then hand the plot to girafe
The workflow has two steps and they are both mandatory. Instead of geom_point you use geom_point_interactive, and instead of geom_sf you use geom_sf_interactive, then you provide at least one of tooltip, data_id or onclick. Finally you call the girafe function with the ggplot object so the graphic is translated into web interactive graphics. Here is the shape of a complete example.
``` r library(ggplot2) library(ggiraph) data <- mtcars data$carname <- row.names(data)
gg_point = ggplot(data = data) + geom_point_interactive(aes(x = wt, y = qsec, color = disp, tooltip = carname, data_id = carname)) + theme_minimal()
girafe(ggobj = gg_point) ```
Note what this produces. girafe returns a web widget object, not a device to print from, so the plot becomes an HTML page element rather than a static image. The tooltip text is a column reference inside aes(), which means it is computed by ggplot2 as usual and passed through as the element text.
Under the hood it is an htmlwidget exporting SVG
The README states the mechanism plainly: under the hood ggiraph is an htmlwidget and a ggplot2 extension, and it allows graphics to be interactive by exporting them as SVG documents and using special attributes on the various elements. That single design choice explains most of the package's behaviour and most of its limits. SVG is a vector format, so the output stays sharp at any zoom, and the DOM nodes carry the tooltip text, the click handler and the id as attributes, which is what lets a browser attach behaviour to a specific point rather than to the whole image. It also means the output is not a PNG, so any pipeline that expected a raster file has to change. The JavaScript half of the package lives in srcjs and is built as a separate module, with the repository holding webpack configuration for development, production and watch builds.
Almost every ggplot2 element has an interactive twin
The layer list is long, and the naming is systematic. Interactive geometries include geom_point_interactive, geom_col_interactive and geom_tile_interactive, alongside geom_abline_interactive, geom_bar_interactive, geom_boxplot_interactive, geom_histogram_interactive, geom_jitter_interactive, geom_path_interactive, geom_polygon_interactive, geom_raster_interactive and others such as geom_count_interactive, geom_density_interactive, geom_hex_interactive and geom_map_interactive. The scales have interactive versions too, with scale_fill_manual_interactive and scale_discrete_manual_interactive named in the README, and the guides include guide_legend_interactive. The point of the naming convention is that an interactive layer is a drop-in replacement that keeps the ggplot2 version of the layer, and the README says the same goes for scales and the few guides. Annotations, titles and facets can also be made interactive, with the details in the interactive_parameters help topic.
Shiny selections land in a reactive value named after the widget
Inside a Shiny application the package becomes two-way rather than one-way. Elements associated with an id through data_id can be selected and manipulated on both the client and the server side, and the list of selected values is stored in a reactive value named [shiny_id]_selected. The interaction surface is wider than geometry here: with Shiny the package allows interaction with graph elements, legend elements, titles and ggplot theme elements from the server part, and each selection is available as a reactive value. The practical pattern is a scatter plot whose points are selectable, with the selection driving other server-side state. The naming convention means you look up the reactive by the widget's shiny id with the _selected suffix, which is worth knowing before you wire up the observer.
Installing from CRAN or from the development branch
There are two installation routes and the README lists both.
``` r install.packages("ggiraph")
r devtools::install_github('davidgohel/ggiraph') ```
The CRAN route is the stable one, and the GitHub route gives you the development version. The package is also documented online at davidgohel.github.io/ggiraph, and there is a longer book at ardata.fr/ggiraph-book that the README points to for usage questions. The repository itself carries the usual R package scaffolding: a DESCRIPTION file, NAMESPACE, R sources, man pages, tests, inst, vignettes, a src directory for compiled code, and a package.json for the JavaScript module that webpack builds.
Compiling on macOS means fixing libpng and Makevars yourself
The source install path has a real dependency that the README does not gloss over. To compile the package from source you need libpng, and using Homebrew is recommended, so you install it with brew install libpng. You then configure your ~/.R/Makevars file with the appropriate paths. On Apple Silicon Macs the typical configuration points the compiler flags at /opt/homebrew/include and the linker flags at /opt/homebrew/lib.
CFLAGS=-I/opt/homebrew/include
CPPFLAGS=-I/opt/homebrew/include
CXXFLAGS=-I/opt/homebrew/include
CXX11FLAGS=-I/opt/homebrew/include
LDFLAGS=-L/opt/homebrew/libIntel Macs use /usr/local/include and /usr/local/lib instead. The README closes that section with a note that paths may vary depending on your system configuration and that the maintainer is unable to provide support for installation issues related to macOS compilation setup. So on macOS, treat the compiler setup as your problem, and note that a binary install from CRAN sidesteps it entirely.
Contributions require an agreed issue first
The contribution policy is unusually strict and worth knowing before you spend an evening on a pull request. Before writing any code you should open an issue describing the change and the reason for it, and the proposal has to be discussed and explicitly validated by the maintainer before work starts. Pull requests for features that did not go through this step will not be considered, no matter how well crafted, and unsolicited pull requests that bypass it will be closed. Once a proposal is agreed, the maintainer invites you to open a pull request for that specific change. When invited, the pull request should include the new functions with code and roxygen tags including runnable examples, documentation updates where relevant, and tests in the directory inst/tinytest. Bug reports have a similar discipline: the issue form requires a reproducible example built with reprex and the output of sessionInfo(), and reports missing those elements are closed without further response.
Editorial conclusion
Use ggiraph when your ggplot2 output has to be a web graphic rather than a static image, either because a reader needs a tooltip on a point or because a Shiny application needs the selected ids back on the server, since the SVG export with attached attributes is the only mechanism on offer. Do not expect it to work for other graphics engines, since the entire package is built around ggplot2 layers and their interactive twins. Verify first that the version you install from CRAN matches your ggplot2, that you can call devtools::install_github('davidgohel/ggiraph') if you need the development version, and on macOS that libpng is present and your ~/.R/Makevars points at the right Homebrew prefix, since the maintainer explicitly declines support for macOS compilation setup.
Frequently asked questions
How do I install ggiraph in R?
Install the CRAN version with install.packages("ggiraph"), or get the development version from GitHub with devtools::install_github('davidgohel/ggiraph'). The package documentation is at davidgohel.github.io/ggiraph.
How do I add a tooltip to a ggplot2 point with ggiraph?
Use geom_point_interactive instead of geom_point and set the tooltip aesthetic inside aes(), then pass the plot to girafe. You need to provide at least one of the tooltip, data_id or onclick aesthetics for an element to become interactive.
How does ggiraph work under the hood?
The README describes it as an htmlwidget and a ggplot2 extension that exports the graphics as SVG documents and uses special attributes on the elements. The JavaScript side is a separate d3 based module built with webpack from the srcjs directory.
Can a Shiny app read the selected elements from a ggiraph plot?
Yes. Elements given a data_id can be selected on the client and the server side, and the selected values are stored in a reactive value named [shiny_id]_selected. In Shiny the package also allows interaction with legend elements, titles and theme elements.
What do I need to compile ggiraph from source on macOS?
You need libpng, which the README recommends installing with brew install libpng, and then you configure ~/.R/Makevars with the right paths, /opt/homebrew/include and /opt/homebrew/lib on Apple Silicon and /usr/local/include and /usr/local/lib on Intel. The maintainer states that support for macOS compilation setup issues cannot be provided.
Official sources
Was this useful?