Reference Guide

Reference for shinyseo

This package generates metadata for a Shiny app and returns HTML tags for <head>.

It is useful when you want the page to look right in shares on Facebook, LinkedIn, X, Slack, and other services that read Open Graph or Twitter Card metadata.

Main flow

  1. Pass a YAML file or a named list to social_meta() in the UI.
  2. social_meta() reads the data, fills in defaults, validates required fields, and builds a tags$head() block with metadata and a JavaScript handler.
  3. Optionally call update_meta() in the server to update one or more fields reactively without a page reload.

Inputs

social_meta(meta) accepts:

Required fields

These must always exist:

  • title
  • description
  • url
  • image

If one is missing, the function stops with an error.

Defaults

If you do not set them yourself, these defaults are used:

What tags are created

The function builds:

Open Graph

These fields are used directly in Open Graph:

Twitter Card

These fields are used directly in Twitter Card:

Bing verification

Bing verification is used directly when the following is set:

If that field is missing, SHINYSEO_BING_SITE_VERIFICATION is used when present.

Schema.org JSON-LD

JSON-LD is created with these base fields:

Additional fields may be included:

If you set schema = FALSE, JSON-LD is omitted entirely.

Custom meta tags

The custom field accepts a list of lists. Each inner list becomes one <meta> tag; its names map directly to HTML attributes.

custom = list(
  list(name     = "viewport",  content = "width=device-width, initial-scale=1"),
  list(property = "og:video",  content = "https://example.no/video.mp4"),
  list(name     = "x-app-env", content = "production")
)

Use name for standard meta tags and property for Open Graph-style tags. Any other valid HTML attribute is also accepted.

Practical example

ui <- shiny::fluidPage(
  shinyseo::social_meta(list(
    title = "Calculator",
    description = "A simple app for calculating things.",
    url = "https://example.no",
    image = "https://example.no/preview.png",
    twitter_site = "@example",
    twitter_creator = "@example",
    schema = TRUE
  )),
  shiny::h1("Calculator")
)

Favicon and web app manifest

Add favicon and PWA support by setting optional fields in the same metadata object:

# global.R
shinyseo::write_manifest(list(
  title            = "My App",
  short_name       = "MyApp",
  description      = "A Shiny web app.",
  theme_color      = "#1a73e8",
  favicon          = "/favicon.svg",
  favicon_png      = "/favicon-32.png",
  apple_touch_icon = "/apple-touch-icon.png"
))
# ui.R
shinyseo::social_meta(list(
  title            = "My App",
  description      = "A Shiny web app.",
  url              = "https://example.no",
  image            = "https://example.no/share.png",
  favicon          = "/favicon.svg",
  favicon_png      = "/favicon-32.png",
  apple_touch_icon = "/apple-touch-icon.png",
  theme_color      = "#1a73e8",
  manifest         = "/manifest.json"
))

Place the icon files in the www/ folder of the app. write_manifest() writes www/manifest.json automatically.

The MIME type for favicon is inferred from the file extension. Supported: .ico, .png, .svg, .webp, .gif. Override with favicon_type if needed.

SVG favicons need a PNG fallback

If favicon is an SVG, also set favicon_png (optionally with favicon_png_sizes, default "32x32"). Chromium-based browsers (Chrome, Edge, Comet, etc.) don’t render SVG favicons in the address bar – without a PNG fallback the address bar shows a generic globe icon even though the browser tab displays the SVG correctly. write_manifest() also includes favicon_png in the generated manifest.json icons.

Reactive metadata with update_meta()

Call update_meta() in the server when the visible content changes — for example when the user switches tabs or navigates between routes. Only the fields you supply are updated; everything else stays as set by social_meta().

ui <- shiny::navbarPage("My App",
  shinyseo::social_meta(list(
    title       = "My App",
    description = "A multi-tab Shiny app.",
    url         = "https://example.no",
    image       = "https://example.no/preview.png"
  )),
  shiny::tabPanel("Home"),
  shiny::tabPanel("About")
)

server <- function(input, output, session) {
  observeEvent(input$tabs, {
    if (input$tabs == "About") {
      shinyseo::update_meta(session,
        title       = "About – My App",
        description = "Learn more about the team."
      )
    } else {
      shinyseo::update_meta(session,
        title       = "My App",
        description = "A multi-tab Shiny app."
      )
    }
  })
}

social_meta() must be present in the UI for the JavaScript handler to be registered.

When to use it

Use the package when you want a small, tidy metadata solution in a Shiny app without building a custom metadata engine.

It is especially useful when you: