Ionic Open Graph Meta Tags: Add OG to Ionic Angular, React, and Vue

How to add og:title, og:image, og:description, and Twitter card meta tags in an Ionic app using Angular Meta service, React Helmet, or Vue useHead.

Ionic and OG tags: what you need to know

Ionic is a cross-platform UI toolkit that targets web, iOS, and Android from a single codebase. When deployed as a Progressive Web App (PWA) or website, Ionic apps are typically client-side rendered — meaning social crawlers won't execute JavaScript and will see an empty <head> unless you handle OG tags correctly.

The approach differs based on your framework: Angular uses the Meta service, React uses react-helmet-async, and Vue uses @vueuse/head. For social preview support, all three approaches need server-side rendering or static generation.

Angular Ionic: Meta service

Angular's built-in Meta and Title services let you set document head tags from any component. For crawler visibility, combine with Angular Universal (SSR) or Angular's static prerendering.

// src/app/pages/post/post.page.ts
import { Component, OnInit } from '@angular/core';
import { Meta, Title } from '@angular/platform-browser';
import { ActivatedRoute } from '@angular/router';
import { PostService } from '../../services/post.service';

@Component({
  selector: 'app-post',
  templateUrl: './post.page.html',
})
export class PostPage implements OnInit {
  constructor(
    private meta: Meta,
    private title: Title,
    private route: ActivatedRoute,
    private postService: PostService,
  ) {}

  async ngOnInit() {
    const slug = this.route.snapshot.params['slug'];
    const post = await this.postService.getPost(slug);

    this.title.setTitle(`${post.title} | My Blog`);

    // Open Graph
    this.meta.updateTag({ property: 'og:type',        content: 'article' });
    this.meta.updateTag({ property: 'og:title',       content: post.title });
    this.meta.updateTag({ property: 'og:description', content: post.excerpt });
    this.meta.updateTag({ property: 'og:image',       content: post.ogImage });
    this.meta.updateTag({ property: 'og:url',         content: `https://yourdomain.com/post/${slug}` });

    // Twitter Card
    this.meta.updateTag({ name: 'twitter:card',        content: 'summary_large_image' });
    this.meta.updateTag({ name: 'twitter:title',       content: post.title });
    this.meta.updateTag({ name: 'twitter:description', content: post.excerpt });
    this.meta.updateTag({ name: 'twitter:image',       content: post.ogImage });
  }
}

For crawler visibility, add @nguniversal/express-engine to your project and run ng add @nguniversal/express-engine to enable Angular Universal SSR.

React Ionic: react-helmet-async

For Ionic React apps, use react-helmet-async to manage head tags. Wrap your app in HelmetProvider and add a Helmet component in each page.

npm install react-helmet-async

// src/App.tsx
import { HelmetProvider } from 'react-helmet-async';

const App: React.FC = () => (
  <HelmetProvider>
    <IonApp>
      <IonReactRouter>
        {/* your routes */}
      </IonReactRouter>
    </IonApp>
  </HelmetProvider>
);

// src/pages/PostPage.tsx
import { Helmet } from 'react-helmet-async';

const PostPage: React.FC = () => {
  const { slug } = useParams<{ slug: string }>();
  const [post, setPost] = useState<Post | null>(null);

  useEffect(() => {
    fetchPost(slug).then(setPost);
  }, [slug]);

  if (!post) return <IonSpinner />;

  return (
    <IonPage>
      <Helmet>
        <title>{post.title} | My Blog</title>
        <meta name="description"         content={post.excerpt} />
        <meta property="og:type"         content="article" />
        <meta property="og:title"        content={post.title} />
        <meta property="og:description"  content={post.excerpt} />
        <meta property="og:image"        content={post.ogImage} />
        <meta property="og:url"          content={`https://yourdomain.com/post/${slug}`} />
        <meta name="twitter:card"        content="summary_large_image" />
        <meta name="twitter:title"       content={post.title} />
        <meta name="twitter:description" content={post.excerpt} />
        <meta name="twitter:image"       content={post.ogImage} />
      </Helmet>
      <IonContent>
        <h1>{post.title}</h1>
      </IonContent>
    </IonPage>
  );
};

Vue Ionic: useHead / @vueuse/head

For Ionic Vue, use @vueuse/head (or @unhead/vue for Nuxt-compatible setups) to manage head tags reactively.

npm install @vueuse/head

// src/main.ts
import { createHead } from '@vueuse/head';
const head = createHead();
app.use(head);

// src/views/PostPage.vue
<script setup lang="ts">
import { useHead } from '@vueuse/head';
import { ref, onMounted } from 'vue';

const route = useRoute();
const post = ref<Post | null>(null);

onMounted(async () => {
  post.value = await fetchPost(route.params.slug as string);
});

useHead(computed(() => ({
  title: post.value ? `${post.value.title} | My Blog` : 'Loading...',
  meta: post.value ? [
    { name: 'description',          content: post.value.excerpt },
    { property: 'og:type',          content: 'article' },
    { property: 'og:title',         content: post.value.title },
    { property: 'og:description',   content: post.value.excerpt },
    { property: 'og:image',         content: post.value.ogImage },
    { property: 'og:url',           content: `https://yourdomain.com/post/${route.params.slug}` },
    { name: 'twitter:card',         content: 'summary_large_image' },
    { name: 'twitter:title',        content: post.value.title },
    { name: 'twitter:image',        content: post.value.ogImage },
  ] : [],
})));
</script>

Capacitor deep links and OG tags

When sharing deep links from a Capacitor app (iOS/Android), users often share the app's web URL. If your Ionic web app has proper OG tags, those deep link previews will look great in iMessage, WhatsApp, and other messaging apps.

For native Capacitor apps, OG tags only apply to the web layer. The native app share sheet uses the OS's own preview — not OG tags. Focus your OG tag efforts on the web version of your Ionic app.

OG tag checklist for Ionic

  • Use Angular Universal, React SSR, or Nuxt/SSG for crawler-visible OG tags.
  • For Angular: use the Meta service per route.
  • For React: wrap app in HelmetProvider and use per-page Helmet.
  • For Vue: use @vueuse/head with useHead().
  • Set twitter:card to summary_large_image.
  • Use absolute URLs for og:image (1200×630 px).

Preview your Ionic app's social cards

Paste your Ionic web app URL into OGFixer to see how it previews on Twitter, LinkedIn, Discord, and Slack.

Related Guides