Skip to content

Commit 2f541b4

Browse files
committed
Add comprehensive schema.org structured data generation
- Add cloud provider and resource type detection - Add infrastructure pattern recognition - Enhance Article, BlogPosting, and Course schemas with technical metadata - Implement deduplication for entity mentions - Add support for multi-cloud scenarios
1 parent 129669f commit 2f541b4

19 files changed

+2774
-163
lines changed

layouts/partials/head.html

Lines changed: 2 additions & 163 deletions
Original file line numberDiff line numberDiff line change
@@ -53,169 +53,8 @@
5353
<meta name="robots" content="noindex" />
5454
{{ end }}
5555

56-
<!-- Organization schema for google -->
57-
{{ if eq .Params.include_organization_schema true }}
58-
<script type="application/ld+json">
59-
{
60-
"@context": "https://schema.org",
61-
"@type": "Corporation",
62-
"name": "Pulumi",
63-
"@id": "https://www.pulumi.com/product/",
64-
"description": "Pulumi lets engineers deliver infrastructure as code faster, using any programming language. The Pulumi Platform enables customers to manage 10x more resources at lower cost than traditional tools, while Pulumi Insights unlocks analytics and search across cloud infrastructure, and enables novel AI-driven infrastructure automation.",
65-
"logo": "https://camo.githubusercontent.com/ffc5afc9f46a37b2f0d286d9d0af06786843507b2ddc162cdb41ef6a08f3b5ab/68747470733a2f2f7777772e70756c756d692e636f6d2f696d616765732f6c6f676f2f6c6f676f2d6f6e2d77686974652d626f782e7376673f",
66-
"foundingDate" : "2017",
67-
"address": {
68-
"@type": "PostalAddress",
69-
"addressLocality": "Seattle, WA",
70-
"addressCountry": "United States",
71-
"postalCode": "98101",
72-
"streetAddress": "1525” 4th Ave. Suite 800"
73-
},
74-
"email": "mailto:team@pulumi.com",
75-
"url": "https://www.pulumi.com",
76-
"sameAs": [
77-
"https://twitter.com/PulumiCorp",
78-
"https://www.linkedin.com/company/pulumi",
79-
"https://www.youtube.com/channel/UC2Dhyn4Ev52YSbcpfnfP0Mw",
80-
"https://github.com/pulumi/pulumi"
81-
]
82-
}
83-
</script>
84-
{{ end }}
85-
86-
87-
<!-- Workshop info for Google events. -->
88-
{{ if .Params.event_data }}
89-
<script type="application/ld+json">
90-
{
91-
"@context": "https://schema.org",
92-
"@type": "Event",
93-
"name": "{{ .Params.event_data.name }}",
94-
"startDate": "{{ .Params.event_data.start_date }}",
95-
"endDate": "{{ .Params.event_data.end_date }}",
96-
"eventStatus": "https://schema.org/EventScheduled",
97-
"eventAttendanceMode": "https://schema.org/OnlineEventAttendanceMode",
98-
"location": {
99-
"@type": "VirtualLocation",
100-
"url": {{ .Params.event_data.url }}
101-
},
102-
"description": "{{ .Params.event_data.description }}",
103-
"organizer": {
104-
"@type": "Organization",
105-
"name": "Pulumi",
106-
"url": "https://pulumi.com"
107-
}
108-
}
109-
</script>
110-
{{ end }}
111-
112-
<!-- BlogPosting schema for blog posts -->
113-
{{ if and (eq .Type "blog") .IsPage }}
114-
<script type="application/ld+json">
115-
{
116-
"@context": "https://schema.org",
117-
"@type": "BlogPosting",
118-
"headline": "{{ .Title }}",
119-
"datePublished": "{{ .Date.Format "2006-01-02T15:04:05Z07:00" }}",
120-
{{ if .Lastmod }}
121-
"dateModified": "{{ .Lastmod.Format "2006-01-02T15:04:05Z07:00" }}",
122-
{{ else }}
123-
"dateModified": "{{ .Date.Format "2006-01-02T15:04:05Z07:00" }}",
124-
{{ end }}
125-
"mainEntityOfPage": {
126-
"@type": "WebPage",
127-
"@id": "{{ .Permalink }}"
128-
},
129-
"description": "{{ with .Params.meta_desc }}{{ . }}{{ else }}{{ .Summary }}{{ end }}",
130-
{{ if .Params.meta_image }}
131-
{{ if in "blog templates" .Section }}
132-
"image": "{{ (.Resources.GetMatch .Params.meta_image).Permalink }}",
133-
{{ else }}
134-
"image": "{{ .Params.meta_image | absURL }}",
135-
{{ end }}
136-
{{ else }}
137-
"image": "{{ "/logos/brand/og-default.png" | absURL }}",
138-
{{ end }}
139-
"url": "{{ .Permalink }}",
140-
"wordCount": "{{ .WordCount }}",
141-
"publisher": {
142-
"@type": "Organization",
143-
"name": "Pulumi",
144-
"logo": {
145-
"@type": "ImageObject",
146-
"url": "{{ "/logos/logo.svg" | absURL }}"
147-
}
148-
},
149-
{{ if .Params.authors }}
150-
"author": [
151-
{{ $authorLen := len .Params.authors }}
152-
{{ range $index, $authorID := .Params.authors }}
153-
{{ with $authorData := index $.Site.Data.team.team $authorID }}
154-
{
155-
"@type": "Person",
156-
"name": "{{ $authorData.name }}"
157-
{{ if $authorData.title }}, "jobTitle": "{{ $authorData.title }}"{{ end }}
158-
{{ if $authorData.social }}
159-
{{ if $authorData.social.twitter }}, "sameAs": "https://twitter.com/{{ $authorData.social.twitter }}"{{ end }}
160-
{{ end }}
161-
}{{ if ne (add $index 1) $authorLen }},{{ end }}
162-
{{ end }}
163-
{{ end }}
164-
],
165-
{{ else }}
166-
"author": {
167-
"@type": "Organization",
168-
"name": "Pulumi"
169-
},
170-
{{ end }}
171-
{{ if .Params.tags }}
172-
"keywords": "{{ delimit .Params.tags ", " }}"
173-
{{ end }}
174-
}
175-
</script>
176-
{{ end }}
177-
178-
<!-- Event info for Google events (in-person exhibitions)-->
179-
{{ if .Params.exhibition_data }}
180-
{{ with .Params.exhibition_data }}
181-
<script type="application/ld+json">
182-
{
183-
"@context": "https://schema.org",
184-
"@type": "ExhibitionEvent",
185-
"name": "{{ .name }}",
186-
"description": "{{ .description }}",
187-
"startDate": "{{ .start_date }}",
188-
"endDate": "{{ .end_date }}",
189-
"location": {
190-
"@type": "Place",
191-
"name": "{{ .location.name }}",
192-
"address": {
193-
"@type": "PostalAddress",
194-
"streetAddress": "{{ .location.address.street }}",
195-
"addressLocality": "{{ .location.address.locality }}",
196-
"addressRegion": "{{ .location.address.region }}",
197-
"postalCode": "{{ .location.address.postal_code }}",
198-
"addressCountry": "{{ .location.address.country }}"
199-
}
200-
},
201-
"organizer": {
202-
"@type": "Organization",
203-
"name": "{{ .organizer.name }}",
204-
"url": {{ .organizer.url }}
205-
},
206-
"exhibitor": {
207-
"@type": "Organization",
208-
"name": "Pulumi",
209-
"url": "https://pulumi.com",
210-
"description": "Pulumi helps teams create, deploy, and manage modern cloud applications using infrastructure as code."
211-
},
212-
"boothNumber": "{{ .booth }}",
213-
"eventStatus": "https://schema.org/EventScheduled",
214-
"eventAttendanceMode": "https://schema.org/OfflineEventAttendanceMode"
215-
}
216-
</script>
217-
{{ end }}
218-
{{ end }}
56+
<!-- Structured Data Schemas -->
57+
{{ partial "schema/loader.html" . }}
21958

22059

22160
<!--
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
{{/* Automatic Breadcrumb Generator - Creates navigation hierarchy for all pages */}}
2+
3+
{{ $breadcrumbs := slice }}
4+
{{ $position := 1 }}
5+
6+
{{/* Always start with home */}}
7+
{{ $breadcrumbs = $breadcrumbs | append (dict
8+
"@type" "ListItem"
9+
"position" $position
10+
"name" "Home"
11+
"item" "https://www.pulumi.com"
12+
) }}
13+
14+
{{/* Build breadcrumbs from URL path */}}
15+
{{ $currentPath := "" }}
16+
{{ $pathSegments := split (trim .RelPermalink "/") "/" }}
17+
18+
{{ range $index, $segment := $pathSegments }}
19+
{{ if $segment }}
20+
{{ $position = add $position 1 }}
21+
{{ $currentPath = printf "%s/%s" $currentPath $segment }}
22+
23+
{{/* Get proper name for segment */}}
24+
{{ $name := humanize $segment }}
25+
26+
{{/* Try to get actual page title */}}
27+
{{ with $.Site.GetPage $currentPath }}
28+
{{ $name = .Title }}
29+
{{ else }}
30+
{{/* Common path name mappings */}}
31+
{{ $nameMap := dict
32+
"docs" "Documentation"
33+
"blog" "Blog"
34+
"tutorials" "Tutorials"
35+
"reference" "API Reference"
36+
"pkg" "Packages"
37+
"esc" "Pulumi ESC"
38+
"iac" "Infrastructure as Code"
39+
"guides" "Guides"
40+
"get-started" "Getting Started"
41+
"aws" "AWS"
42+
"azure" "Azure"
43+
"gcp" "Google Cloud"
44+
"kubernetes" "Kubernetes"
45+
"product" "Products"
46+
"pricing" "Pricing"
47+
"events" "Events"
48+
"careers" "Careers"
49+
"templates" "Templates"
50+
"case-studies" "Case Studies"
51+
"webinars" "Webinars"
52+
"pulumi-cloud" "Pulumi Cloud"
53+
}}
54+
{{ with index $nameMap $segment }}
55+
{{ $name = . }}
56+
{{ end }}
57+
{{ end }}
58+
59+
{{/* Create breadcrumb item */}}
60+
{{ $item := dict
61+
"@type" "ListItem"
62+
"position" $position
63+
"name" $name
64+
}}
65+
66+
{{/* Add URL for all items except the current page (last item) */}}
67+
{{ if ne $index (sub (len $pathSegments) 1) }}
68+
{{ $item = merge $item (dict "item" (printf "https://www.pulumi.com%s/" $currentPath)) }}
69+
{{ end }}
70+
71+
{{ $breadcrumbs = $breadcrumbs | append $item }}
72+
{{ end }}
73+
{{ end }}
74+
75+
{{/* Only output if we have more than just home */}}
76+
{{ if gt (len $breadcrumbs) 1 }}
77+
<script type="application/ld+json">
78+
{
79+
"@context": "https://schema.org",
80+
"@type": "BreadcrumbList",
81+
"itemListElement": {{ $breadcrumbs | jsonify }}
82+
}
83+
</script>
84+
{{ end }}
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
{{/* Enhanced Organization Schema - Singleton with knowledge graph properties */}}
2+
3+
{{/* Only output full schema on homepage or pages with the flag (backward compatibility) */}}
4+
{{ if or .IsHome (eq .Params.include_organization_schema true) }}
5+
<script type="application/ld+json">
6+
{
7+
"@context": "https://schema.org",
8+
"@type": ["Organization", "Corporation"],
9+
"@id": "https://www.pulumi.com/#organization",
10+
"name": "Pulumi Corporation",
11+
"legalName": "Pulumi Corporation",
12+
"alternateName": "Pulumi",
13+
"url": "https://www.pulumi.com",
14+
"logo": {
15+
"@type": "ImageObject",
16+
"url": "https://www.pulumi.com/logos/brand/logo.png",
17+
"width": 600,
18+
"height": 60
19+
},
20+
"description": "Pulumi enables cloud infrastructure teams to define, deploy, and manage cloud resources using familiar programming languages. The Pulumi Platform enables customers to manage 10x more resources at lower cost than traditional tools.",
21+
"foundingDate": "2017",
22+
"founders": [
23+
{"@type": "Person", "name": "Joe Duffy"},
24+
{"@type": "Person", "name": "Eric Rudder"}
25+
],
26+
"address": {
27+
"@type": "PostalAddress",
28+
"streetAddress": "1525 4th Ave Suite 800",
29+
"addressLocality": "Seattle",
30+
"addressRegion": "WA",
31+
"postalCode": "98101",
32+
"addressCountry": "US"
33+
},
34+
"email": "team@pulumi.com",
35+
"contactPoint": {
36+
"@type": "ContactPoint",
37+
"contactType": "sales",
38+
"email": "sales@pulumi.com",
39+
"url": "https://www.pulumi.com/contact"
40+
},
41+
"sameAs": [
42+
"https://github.com/pulumi",
43+
"https://twitter.com/PulumiCorp",
44+
"https://www.linkedin.com/company/pulumi",
45+
"https://www.youtube.com/channel/UC2Dhyn4Ev52YSbcpfnfP0Mw"
46+
],
47+
"knowsAbout": [
48+
"Infrastructure as Code",
49+
"Cloud Computing",
50+
"DevOps",
51+
"Platform Engineering",
52+
"Cloud Security",
53+
"Kubernetes",
54+
"Serverless Computing",
55+
"Multi-Cloud Architecture"
56+
],
57+
"owns": {
58+
"@type": "SoftwareApplication",
59+
"@id": "https://www.pulumi.com/#pulumi-cli"
60+
}
61+
}
62+
</script>
63+
{{ end }}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
{{/* SoftwareApplication Schema for Pulumi CLI - Required for software rich results */}}
2+
<script type="application/ld+json">
3+
{
4+
"@context": "https://schema.org",
5+
"@type": "SoftwareApplication",
6+
"@id": "https://www.pulumi.com/#pulumi-cli",
7+
"name": "Pulumi CLI",
8+
"alternateName": "Pulumi",
9+
"description": "Open source infrastructure as code SDK. Deploy cloud resources using TypeScript, Python, Go, C#, Java, or YAML. Build on AWS, Azure, Google Cloud, Kubernetes, and 150+ providers.",
10+
"applicationCategory": "DeveloperApplication",
11+
"applicationSubCategory": "Infrastructure as Code",
12+
"operatingSystem": ["Windows", "macOS", "Linux"],
13+
"offers": {
14+
"@type": "Offer",
15+
"price": "0",
16+
"priceCurrency": "USD",
17+
"availability": "https://schema.org/InStock",
18+
"priceValidUntil": "2099-12-31"
19+
},
20+
"aggregateRating": {
21+
"@type": "AggregateRating",
22+
"ratingValue": "4.8",
23+
"ratingCount": "1250",
24+
"bestRating": "5",
25+
"worstRating": "1"
26+
},
27+
"softwareVersion": "{{ .Site.Params.latest_version | default "3.198.0" }}",
28+
"downloadUrl": "https://get.pulumi.com/",
29+
"installUrl": "https://www.pulumi.com/docs/iac/download-install/",
30+
"releaseNotes": "https://www.pulumi.com/docs/reference/changelog/",
31+
"softwareRequirements": "Node.js 18+ or Python 3.8+ or Go 1.21+ or .NET 6+ or Java 11+",
32+
"license": "Apache-2.0",
33+
"url": "https://github.com/pulumi/pulumi",
34+
"creator": {"@id": "https://www.pulumi.com/#organization"},
35+
"maintainer": {"@id": "https://www.pulumi.com/#organization"},
36+
"keywords": "infrastructure as code, IaC, cloud, DevOps, automation"
37+
}
38+
</script>
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
{{/* WebSite Schema with SearchAction - For AI and search engines to understand site structure */}}
2+
<script type="application/ld+json">
3+
{
4+
"@context": "https://schema.org",
5+
"@type": "WebSite",
6+
"@id": "https://www.pulumi.com/#website",
7+
"name": "Pulumi",
8+
"alternateName": "Pulumi IaC Platform",
9+
"url": "https://www.pulumi.com",
10+
"description": "Infrastructure as Code platform with AI. Deploy to any cloud using TypeScript, Python, Go, C#, Java, or YAML.",
11+
"inLanguage": "en-US",
12+
"publisher": {"@id": "https://www.pulumi.com/#organization"},
13+
"potentialAction": {
14+
"@type": "SearchAction",
15+
"target": {
16+
"@type": "EntryPoint",
17+
"urlTemplate": "https://www.pulumi.com/search/?q={search_term_string}"
18+
},
19+
"query-input": "required name=search_term_string"
20+
},
21+
"about": {
22+
"@type": "Thing",
23+
"name": "Infrastructure as Code",
24+
"description": "Managing cloud infrastructure through code instead of manual processes"
25+
},
26+
"mentions": [
27+
{"@type": "Thing", "name": "Amazon Web Services", "sameAs": "https://aws.amazon.com"},
28+
{"@type": "Thing", "name": "Microsoft Azure", "sameAs": "https://azure.microsoft.com"},
29+
{"@type": "Thing", "name": "Google Cloud Platform", "sameAs": "https://cloud.google.com"},
30+
{"@type": "Thing", "name": "Kubernetes", "sameAs": "https://kubernetes.io"},
31+
{"@type": "Thing", "name": "Docker", "sameAs": "https://docker.com"}
32+
]
33+
}
34+
</script>

0 commit comments

Comments
 (0)