Structured data tells search engines about your content in a machine-readable format. For mobile apps, structured data serves two purposes: it can generate rich results in search (showing app ratings, prices, and screenshots) and it connects your web content to your app via deep link annotations.
This guide covers the specific schema.org types and properties relevant to app content, with implementation examples. For the broader app indexing setup, see Google App Indexing. For getting app content into search, see app content in search results.
How Structured Data Works for Apps
Search engines parse structured data from your web pages to understand:
- What your content is (product, article, recipe, software application).
- What actions are available (view, buy, download, play).
- Where those actions can be performed (website, Android app, iOS app).
When Google sees structured data declaring that a product page can be viewed in an Android app, it may show an "Open in app" button in mobile search results.
SoftwareApplication Schema
For your app's main landing page, use the SoftwareApplication type:
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "SoftwareApplication",
"name": "YourApp",
"operatingSystem": "Android, iOS",
"applicationCategory": "FinanceApplication",
"description": "Track expenses, set budgets, and manage your personal finances.",
"url": "https://www.yourapp.com",
"downloadUrl": [
"https://play.google.com/store/apps/details?id=com.yourapp.android",
"https://apps.apple.com/app/yourapp/id123456789"
],
"screenshot": [
{
"@type": "ImageObject",
"url": "https://www.yourapp.com/images/screenshot-1.png",
"caption": "Budget overview dashboard"
},
{
"@type": "ImageObject",
"url": "https://www.yourapp.com/images/screenshot-2.png",
"caption": "Expense tracking screen"
}
],
"author": {
"@type": "Organization",
"name": "YourApp Inc.",
"url": "https://www.yourapp.com"
},
"offers": {
"@type": "Offer",
"price": "0",
"priceCurrency": "USD"
},
"aggregateRating": {
"@type": "AggregateRating",
"ratingValue": "4.7",
"ratingCount": "12500",
"bestRating": "5"
}
}
</script>
MobileApplication Subtype
For more specificity, use MobileApplication:
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "MobileApplication",
"name": "YourApp",
"operatingSystem": "Android 8.0+",
"applicationCategory": "FinanceApplication",
"storageRequirements": "25 MB",
"permissions": "Camera, Location (optional)",
"offers": {
"@type": "Offer",
"price": "0",
"priceCurrency": "USD",
"availability": "https://schema.org/InStock"
}
}
</script>
What This Generates
Google may show a rich result card:
YourApp - Budget Tracker
★★★★★ 4.7 (12,500) · Free · Finance
Track expenses, set budgets, and manage your personal finances.
This rich result has a higher CTR than a plain blue link because it shows the rating, price, and category directly in the SERP.
ViewAction for Deep Linking
The potentialAction property with ViewAction tells search engines that content can be opened in an app:
Basic ViewAction
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "WebPage",
"name": "Summer Collection",
"url": "https://www.yourapp.com/collections/summer",
"potentialAction": {
"@type": "ViewAction",
"target": "https://www.yourapp.com/collections/summer"
}
}
</script>
When combined with assetlinks.json and apple-app-site-association verification, Google knows this URL opens in your app.
ViewAction with Explicit App Target
For more control, specify the app target explicitly:
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "Product",
"name": "Running Shoes X",
"url": "https://www.yourapp.com/products/running-shoes-x",
"potentialAction": {
"@type": "ViewAction",
"target": [
"https://www.yourapp.com/products/running-shoes-x",
{
"@type": "EntryPoint",
"urlTemplate": "android-app://com.yourapp.android/https/www.yourapp.com/products/running-shoes-x",
"actionPlatform": [
"https://schema.org/AndroidPlatform"
]
},
{
"@type": "EntryPoint",
"urlTemplate": "https://www.yourapp.com/products/running-shoes-x",
"actionPlatform": [
"https://schema.org/IOSPlatform"
]
}
]
}
}
</script>
This declares that the product page can be viewed on Android (via App Links), iOS (via Universal Links), and the web.
Content-Type-Specific Markup
Different content types use different schema.org types. Here are the most common for app content:
Products
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "Product",
"name": "Wireless Earbuds Pro",
"description": "Noise-cancelling wireless earbuds with 24-hour battery life",
"image": "https://www.yourapp.com/images/earbuds-pro.jpg",
"brand": {
"@type": "Brand",
"name": "AudioBrand"
},
"offers": {
"@type": "Offer",
"price": "79.99",
"priceCurrency": "USD",
"availability": "https://schema.org/InStock",
"url": "https://www.yourapp.com/products/earbuds-pro"
},
"aggregateRating": {
"@type": "AggregateRating",
"ratingValue": "4.5",
"reviewCount": "340"
},
"potentialAction": {
"@type": "ViewAction",
"target": "https://www.yourapp.com/products/earbuds-pro"
}
}
</script>
Articles
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "Article",
"headline": "How to Start Running: A Beginner's Guide",
"author": {
"@type": "Person",
"name": "Jane Smith"
},
"datePublished": "2026-01-15",
"dateModified": "2026-03-01",
"publisher": {
"@type": "Organization",
"name": "YourApp",
"logo": {
"@type": "ImageObject",
"url": "https://www.yourapp.com/logo.png"
}
},
"image": "https://www.yourapp.com/images/running-guide.jpg",
"potentialAction": {
"@type": "ViewAction",
"target": "https://www.yourapp.com/articles/running-beginners-guide"
}
}
</script>
Recipes
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "Recipe",
"name": "Classic Margherita Pizza",
"author": {"@type": "Person", "name": "Chef Mario"},
"datePublished": "2026-02-10",
"prepTime": "PT20M",
"cookTime": "PT15M",
"totalTime": "PT35M",
"recipeYield": "4 servings",
"recipeCategory": "Main Course",
"recipeCuisine": "Italian",
"recipeIngredient": [
"500g pizza dough",
"200g mozzarella",
"100g tomato sauce",
"Fresh basil"
],
"recipeInstructions": [
{
"@type": "HowToStep",
"text": "Preheat oven to 250C (480F)."
},
{
"@type": "HowToStep",
"text": "Roll out dough on a floured surface."
}
],
"potentialAction": {
"@type": "ViewAction",
"target": "https://www.yourapp.com/recipes/margherita-pizza"
}
}
</script>
Events
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "Event",
"name": "Summer Music Festival 2026",
"startDate": "2026-07-15T18:00:00",
"endDate": "2026-07-15T23:00:00",
"location": {
"@type": "Place",
"name": "Central Park",
"address": "New York, NY"
},
"offers": {
"@type": "Offer",
"price": "75",
"priceCurrency": "USD",
"url": "https://www.yourapp.com/events/summer-festival"
},
"potentialAction": {
"@type": "ViewAction",
"target": "https://www.yourapp.com/events/summer-festival"
}
}
</script>
Implementation Patterns
Server-Side Rendering
Generate structured data on the server for each page:
// Express.js example
app.get('/products/:id', async (req, res) => {
const product = await getProduct(req.params.id);
const structuredData = {
"@context": "https://schema.org",
"@type": "Product",
"name": product.name,
"description": product.description,
"image": product.imageUrl,
"url": `https://www.yourapp.com/products/${product.id}`,
"offers": {
"@type": "Offer",
"price": product.price,
"priceCurrency": "USD"
},
"potentialAction": {
"@type": "ViewAction",
"target": `https://www.yourapp.com/products/${product.id}`
}
};
res.render('product', {
product,
structuredData: JSON.stringify(structuredData)
});
});
Template Helper
Create a reusable function for generating structured data:
function appViewAction(url) {
return {
"@type": "ViewAction",
"target": [
url,
{
"@type": "EntryPoint",
"urlTemplate": `android-app://com.yourapp.android/https/www.yourapp.com${new URL(url).pathname}`,
"actionPlatform": ["https://schema.org/AndroidPlatform"]
}
]
};
}
// Usage
const productSchema = {
"@context": "https://schema.org",
"@type": "Product",
"name": product.name,
"potentialAction": appViewAction(`https://www.yourapp.com/products/${product.id}`)
};
Validation and Testing
Google's Rich Results Test
Use the Rich Results Test to validate your structured data. Enter your URL and verify:
- No errors in the structured data.
- All required properties are present.
- The preview shows the expected rich result.
Schema.org Validator
Use the Schema.org Validator for general schema validation (not Google-specific).
Search Console Enhancement Report
After deploying structured data, monitor the Enhancement reports in Google Search Console:
- Valid items: Pages with correctly parsed structured data.
- Warnings: Non-critical issues (missing optional properties).
- Errors: Critical issues that prevent rich results (missing required properties, invalid values).
Common Errors
| Error | Fix |
|---|---|
Missing @context |
Add "@context": "https://schema.org" |
Invalid price value |
Use a number string, not text ("79.99", not "$79.99") |
Missing image |
Add an image URL for any type that requires it |
| Invalid date format | Use ISO 8601 format ("2026-01-15") |
Mismatched @type and properties |
Ensure properties match the declared type |
Tolinku and Structured Data
Tolinku provides the deep link routing that potentialAction targets point to. When you configure routes in the Tolinku dashboard, the URLs work as both web page links and app deep links, making your ViewAction targets functional for both web users and app users.
For Google App Indexing setup, see Google App Indexing. For the broader strategy, see app indexing and SEO for mobile apps.
Get deep linking tips in your inbox
One email per week. No spam.