I was testing game links for PuntuQuest, my punctuation riddle game. A link like puntuquest.com/c/<code> opens the game straight in the app when you tap it in Messages. Without the app, it lands on a small page with an App Store button.
While looking at that page on my phone, I remembered something I'd seen on other websites: a slim bar across the top of Safari with the app's icon and an Open button, or Get if the app isn't installed. I assumed that needed some SDK that checks what's on your phone, so I went looking for one.
There isn't one. It's built into Safari, and it's called a Smart App Banner.
One meta tag
<meta name="apple-itunes-app" content="app-id=6785767085">That's the whole thing. The number is your app's App Store id, the one in your listing's URL (apps.apple.com/app/id6785767085).
With that tag in the page's <head>, Safari on an iPhone draws the banner itself: your app's icon and name, and a button. If the app is installed, the button says Open and opens it. If it isn't, the button takes you to the App Store. Your website never learns which apps someone has, and it doesn't need to. Safari already knows.
In Next.js
If your site is on Next.js, you don't write the tag by hand. The Metadata API has an itunes field for it. In the root layout:
export const metadata: Metadata = {
// ...the rest of your metadata
itunes: { appId: "6785767085" },
};Next.js renders it as the apple-itunes-app meta tag on every page.
Sending people to the right screen
The tag takes a second value, app-argument. It's a URL that Safari hands to your app when someone taps Open. Your app can read it and go straight to the right screen instead of the home screen.
On PuntuQuest's game link pages, I pass the link itself, so Open is meant to land the player on that game, not just the app's home screen:
export async function generateMetadata({ params }: PageProps<"/c/[code]">): Promise<Metadata> {
const { code } = await params;
return {
itunes: {
appId: "6785767085",
appArgument: `https://puntuquest.com/c/${code}`,
},
};
}On the page, that becomes:
<meta name="apple-itunes-app" content="app-id=6785767085, app-argument=https://puntuquest.com/c/Ab3dEf9h">One small thing I did along the way: the App Store id was already typed into the site's download buttons. I moved it into one constant that the buttons and the banner both use, so they can't drift apart.
What it doesn't do
- It only shows in Safari on iPhone and iPad. Chrome on iOS and the browsers built into WhatsApp, Instagram or X don't show it. A lot of links get opened inside those apps, so the banner doesn't replace a proper download button on the page.
- It doesn't replace universal links. A universal link opens the app directly when someone taps it, before any website loads. The banner covers the cases where the website opened anyway: a link pasted into Safari's address bar, or a first tap right after installing.
- It doesn't follow someone through an install. If they tap Get, install and open the app, the app starts fresh. It doesn't know which page they came from. Carrying that through an install is called deferred deep linking, and that's where services like Branch or AppsFlyer come in.
- Once someone closes it, Safari stops showing it to them, so it won't nag anyone who has said no.
Where I've put it
I added it to puntuquest.com and to foodpilot.app, the site for my other app, FoodPilot. It took one line in each root layout, plus the per-page version on PuntuQuest's game links.
Cover photo by Mariia Berezovsky on Unsplash

