I am attempting to test Gmail's capabilities to process embedded JSON-LD in an HTML message in order to show the relevant action in the Inbox view, the introduction of which is described here. I have sent myself a message (using the Python API), for which I expect Gmail to render my View Action, an example of which is shown here. However, nothing is happening. I am expecting to see a link for "View File", similar to one that would be displayed for flight reservations, etc.
I'm trying to understand if there is a problem with my particular JSON-LD content, or if I'm trying to do something that isn't supported. The relevant JSON-LD segment, as embedded in the <body>, is this:
<script type="application/ld+json">
{
"#context": "http://schema.org",
"#type": "CreativeWork",
"#id": "http://my-site.com/file/1",
"additionalType": "http://www.productontology.org/id/Computer_file",
"name": "My File",
"description": "View this file",
"url": "http://my-site.com/file/1",
"action": {
"#type": "ViewAction",
"url": "http://my-site.com/file/1",
"name": "View File"
}
}
</script>
In case there is some issue with the way the email is encoded, here it is in raw format (personal info redacted)
Received: from 874510238733-ktbae5ftk223du75th86q0uua7i7rp5v.apps.googleusercontent.com
named unknown
by gmailapi.google.com
with HTTPREST;
Fri, 6 Mar 2015 14:54:52 -0800
Content-Type: multipart/alternative;
boundary="===============5111695568485418487=="
MIME-Version: 1.0
to: ****#gmail.com
subject: A file has been shared to your email
Date: Fri, 6 Mar 2015 14:54:52 -0800
Message-Id: <CADTCK+Vyd-bKWBJXMcs8eS1zQ-b34BanFzNKOBMVf_2dBiPB3A#mail.gmail.com>
From: ****#gmail.com
--===============5111695568485418487==
Content-Type: text/text; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
A new file is available. View this file <http://my-site.com/file/1>
--===============5111695568485418487==
Content-Type: text/html; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
<html>
<body>
<script type="application/ld+json">
{
"#context": "http://schema.org",
"#type": "CreativeWork",
"#id": "http://my-site.com/file/1",
"additionalType": "http://www.productontology.org/id/Computer_file",
"name": "My File",
"description": "View this file",
"url": "http://my-site.com/file/1",
"action": {
"#type": "ViewAction",
"url": "http://my-site.com/file/1",
"name": "View File"
}
}
</script>
<div>A new file is available. View this file</div>
</body>
</html>
--===============5111695568485418487==--
Related
Im trying to add gmail markups to the top of the order confirmation email like showed in the picture
I tried using the gmail provided markup code:
<script type="application/ld+json">
{
"#context": "http://schema.org",
"#type": "Order",
"merchant": {
"#type": "Organization",
"name": "Amazon.com"
},
"orderNumber": "123-4567890-1234567",
"priceCurrency": "USD",
"price": "29.99",
"acceptedOffer": {
"#type": "Offer",
"itemOffered": {
"#type": "Product",
"name": "Google Chromecast"
},
"price": "29.99",
"priceCurrency": "USD",
"eligibleQuantity": {
"#type": "QuantitativeValue",
"value": "1"
}
}
}
</script>
But with no luck.
Im using a docker with magento 2 and mailhog (locally). Mailhog recieves the order mail. The script exists in the <head> part (with inspect element) but does not get rendeded.
Also tried to sned that exact code using gmail.com to myself - it does not get rendered either.
What im missing?
I can't for the life of me figure out how this company adding this meta data to their Google search.
Does anyone know how to add the data and booking links like the below image?
Thanks
What you are seeing in these search results is what Google defines as "Rich Results" more information can be viewed in Google's Structured Data documentation. Specifically Edgewater Medical center is taking advantage of the event functionality to define times and dates.
This can be verified by pasting the page's source in the Rich Results Test tool, results for this page can be viewed at
https://search.google.com/test/rich-results?utm_campaign=devsite&utm_medium=jsonld&utm_source=event&id=m1ZrUywePCZ_NglFJIjZfg
According to google documentation in order to make this happen you have to follow a few steps:
Ensure that Googlebot can crawl your event pages (meaning, your pages
aren't protected by a robots.txt file or robots meta tag).
Ensure that your server can handle increased crawl rate.
Make sure you follow the Google guidelines.
Add structured data to your event pages. Currently, the event experience on Google only supports pages that focus on a single event. We recommend focusing on adding markup to your event posting pages instead of pages that list schedules or multiple events.
An example of such "structured data" for a standard event is shown below:
<html>
<head>
<title>The Adventures of Kira and Morrison</title>
<script type="application/ld+json">
{
"#context": "https://schema.org",
"#type": "Event",
"name": "The Adventures of Kira and Morrison",
"startDate": "2025-07-21T19:00-05:00",
"endDate": "2025-07-21T23:00-05:00",
"eventAttendanceMode": "https://schema.org/OfflineEventAttendanceMode",
"eventStatus": "https://schema.org/EventScheduled",
"location": {
"#type": "Place",
"name": "Snickerpark Stadium",
"address": {
"#type": "PostalAddress",
"streetAddress": "100 West Snickerpark Dr",
"addressLocality": "Snickertown",
"postalCode": "19019",
"addressRegion": "PA",
"addressCountry": "US"
}
},
"image": [
"https://example.com/photos/1x1/photo.jpg",
"https://example.com/photos/4x3/photo.jpg",
"https://example.com/photos/16x9/photo.jpg"
],
"description": "The Adventures of Kira and Morrison is coming to Snickertown in a can’t miss performance.",
"offers": {
"#type": "Offer",
"url": "https://www.example.com/event_offer/12345_201803180430",
"price": "30",
"priceCurrency": "USD",
"availability": "https://schema.org/InStock",
"validFrom": "2024-05-21T12:00"
},
"performer": {
"#type": "PerformingGroup",
"name": "Kira and Morrison"
},
"organizer": {
"#type": "Organization",
"name": "Kira and Morrison Music",
"url": "https://kiraandmorrisonmusic.com"
}
}
</script>
</head>
<body>
</body>
</html>
I'm adding EventReservation JSON-LD into email (sent from me to me using gmail API from Chrome Extension).
It is successfully delivered into my inbox, but google doesn't recognize this as an event. Here it is email body dump from delivered email (HTML part is successfully validated by google structured data testing tool and yandex structured data validator, and actually json is copy-pasted from an real event that was parsed in my Inbox, so script should be good):
Received: from 236444161893
named unknown
by gmailapi.google.com
with HTTPREST;
Sat, 26 Mar 2016 07:34:52 -0400
From: XXXXXXX#gmail.com
To: XXXXXXX#gmail.com
Subject: Lets Celebrate !
Content-Type: text/html; charset="utf-8"
Date: Sat, 26 Mar 2016 07:34:52 -0400
Message-Id: <CAEY7X7rQZFQTmYqyH-UEMt5KR3bwbC5D-KhT3Rv8vKixVrGkFA#mail.gmail.com>
<html>
<head>
<title>Sample Title</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
<script type="application/ld+json">
{
"#context": "http://schema.org",
"#type": "EventReservation",
"reservationNumber": "123123123",
"underName": {
"#type": "Person",
"name": "John Smith"
},
"reservationStatus": "http://schema.org/Confirmed",
"reservationFor": {
"#type": "Event",
"name": "ProductCamp Helsinki 2016",
"startDate": "2016-04-09T10:00:00+03:00",
"endDate": "2016-04-09T16:00:00+03:00",
"location": {
"#type": "Place",
"name": "OP Headquarters",
"address": {
"#type": "PostalAddress",
"streetAddress": "Teollisuuskatu 1E00510 Helsinki",
"addressLocality": "Helsinki",
"addressRegion": "",
"postalCode": "00510",
"addressCountry": "FI"
}
}
}
}
</script>
<b>I did it!</b>
</body>
</html>
EventReservation Email in my Inbox
What could be wrong?
UPDATE: This HTML works and parsed by Inbox when I send it through script.google.com (MailApp.sendEmail), but doesn't work if it is sent from Chrome Extension using gmail API (POST https://www.googleapis.com/gmail/v1/users/me/messages/send) . So it looks like something wrong with email headers. E.g. "correct" email sent from script.google.com contains DKIM-Signature etc:
Delivered-To: XXXXXXX#gmail.com
Received: by 10.31.52.16 with SMTP id b16csp631299vka;
Sat, 26 Mar 2016 05:40:04 -0700 (PDT)
X-Received: by 10.31.58.139 with SMTP id h133mr9599567vka.158.1458996004694;
Sat, 26 Mar 2016 05:40:04 -0700 (PDT)
Return-Path: <3JIP2VgkJCcEiluklyzwinthps.jvtiluklyzwinthps.jvt#maestro.bounces.google.com>
Received: from mail-vk0-x245.google.com (mail-vk0-x245.google.com. [2607:f8b0:400c:c05::245])
by mx.google.com with ESMTPS id g188si4468255vkf.94.2016.03.26.05.40.04
for <XXXXXXX#gmail.com>
(version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128);
Sat, 26 Mar 2016 05:40:04 -0700 (PDT)
Received-SPF: pass (google.com: domain of 3JIP2VgkJCcEiluklyzwinthps.jvtiluklyzwinthps.jvt#maestro.bounces.google.com designates 2607:f8b0:400c:c05::245 as permitted sender) client-ip=2607:f8b0:400c:c05::245;
Authentication-Results: mx.google.com;
dkim=pass header.i=#gmail.com;
spf=pass (google.com: domain of 3JIP2VgkJCcEiluklyzwinthps.jvtiluklyzwinthps.jvt#maestro.bounces.google.com designates 2607:f8b0:400c:c05::245 as permitted sender) smtp.mailfrom=3JIP2VgkJCcEiluklyzwinthps.jvtiluklyzwinthps.jvt#maestro.bounces.google.com;
dmarc=pass (p=NONE dis=NONE) header.from=gmail.com
Received: by mail-vk0-x245.google.com with SMTP id e6so159765935vkh.0
for <XXXXXXX#gmail.com>; Sat, 26 Mar 2016 05:40:04 -0700 (PDT)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
d=gmail.com; s=20120113;
h=mime-version:message-id:date:subject:from:to;
bh=AcafBmWjtt8pobLyfk/O93P08+xv/A6AO4gP7r6A0pI=;
b=ZXfhpJnohG6skmBxr4JFYf/743Sy7ckO7PnyUBXytwPNwh3GoULK+LJAyXloqt4hBs
7aoKDtuFsr4o2Q2Q+fexqw3qY8QheK/FG7Mr2lVAfVMDg56tumRIp27B4XmaNyL96S3k
i35hR5B5trQKU/qFENnXCQc5LjFdDLUADzbrs6VMHLZW8I/73Yq7+/JDkHeMmIZMAboz
KN8qyWaFZSJvMGg3NTkurkpBE5oJ6KxCN6cjZKLoUFfbPaqa9cdc0c7w4+fNFK0DzjPT
ESsDEpxS9K/1ZL70xYpUmrBzaIhoOehRfpZRc+P4gXAaPvo36PC1ZJjmgzRD6etHJKSM
VB2w==
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
d=1e100.net; s=20130820;
h=x-gm-message-state:mime-version:message-id:date:subject:from:to;
bh=AcafBmWjtt8pobLyfk/O93P08+xv/A6AO4gP7r6A0pI=;
b=gB2OQWkIc7u6mfjc5l9T6umyFBasInqetcEHqQcXbuymmKS5DpqDE8MwYpI62OmVWV
gqrP3E+lf43acVMjslMWQUXuXJQctZMEKkehiN7eA2QeUQd35vWKpjXpuFRBHHLIcin2
XNC8WqwF95XGITPKI9kG78XhdS8h+BVmxVws/rRUA7yqgP/gALPZzeks70Q1p6dh1zkj
Z88ucz2OeOM55EiFha6gKbuLr+0RfZDsquopvxipJjaJhHkcdLqW9xfLf/kgSvD9PdiL
NMJYsnIcgLZ02VtV0RjgK0+/9M/SPtB28nncx8wqP0Z2/fY1MiH+uWMmaH3lvNmgoTLQ
3dIQ==
X-Gm-Message-State: AD7BkJLZUbRwOBaDX4rnT/kKOc5n3NPdUn4PbtoJeh45PKy3qlm7fE9kOBBa5YLgCLErp694wJeXHnGj7LiR2Q==
MIME-Version: 1.0
X-Received: by 10.31.11.75 with SMTP id 72mr11424050vkl.2.1458996004582; Sat,
26 Mar 2016 05:40:04 -0700 (PDT)
Message-ID: <001a1146937894fe1e052ef2fa6a#google.com>
Date: Sat, 26 Mar 2016 12:40:04 +0000
Subject: Test Email markup - Sat Mar 26 2016 15:40:04 GMT+0300 (EAT)
From: XXXXXXX#gmail.com
To: XXXXXXX#gmail.com
Content-Type: multipart/alternative; boundary=001a1146937894fe08052ef2fa67
--001a1146937894fe08052ef2fa67
Content-Type: text/plain; charset=ISO-8859-1; format=flowed; delsp=yes
I did it!
--001a1146937894fe08052ef2fa67
Content-Type: text/html; charset=ISO-8859-1
<html>
<head>
<title>Sample Title</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
<script type="application/ld+json">
{
"#context": "http://schema.org",
"#type": "EventReservation",
"reservationNumber": "1231231234",
"underName": {
"#type": "Person",
"name": "John Smith"
},
"reservationStatus": "http://schema.org/Confirmed",
"reservationFor": {
"#type": "Event",
"name": "ProductCamp Helsinki 2016",
"startDate": "2016-04-09T10:00:00+03:00",
"endDate": "2016-04-09T16:00:00+03:00",
"location": {
"#type": "Place",
"name": "OP Headquarters",
"address": {
"#type": "PostalAddress",
"streetAddress": "Teollisuuskatu 1E00510 Helsinki",
"addressLocality": "Helsinki",
"addressRegion": "",
"postalCode": "00510",
"addressCountry": "FI"
}
}
}
}
</script>
<b>I did it!</b>
</body>
</html>
--001a1146937894fe08052ef2fa67--
I tried to do the same thing (and asked a similar question) and reached the conclusion that the problem is that Inbox ignores structured data unless the email is authenticated using DKIM (to mitigate against spam). I couldn't work out how to enable authentication using the Gmail API, so I opted for using the Google Apps Script function MailApp.sendEmail() instead, as that does send authenticated emails.
I was wondering how to achieve same email structure as PayPal has.
It looks like this (in Google's Inbox):
But I can't find right type for it here: https://developers.google.com/gmail/markup/reference/
Any idea how to achieve the PayPal-like markup?
Using schema.org/Invoice and schema.org/PayAction, I was able to get the email structure that you've posted from PayPal. It also generated a "View Bill" button, which only shows in Inbox and not Gmail. Check out my example script below. The email markup tester seemed to like it, there were no errors found. Try sending it using this Gmail Schema Tester or through Apps Script with your Gmail account.
<script type="application/ld+json">
[
{
"#context": "http://schema.org",
"#type": "Invoice",
"description": "January 2015 Acme Bill",
"url": "https://www.americanexpress.com",
"accountId": "xxxx-xxxx-xxxx-1234",
"potentialaction": {
"url": "https://example.com",
"#type": "PayAction"
},
"paymentDue": "2020-01-30",
"minimumPaymentDue": {
"#type": "PriceSpecification",
"price": "$15.00"
},
"totalPaymentDue": {
"#type": "PriceSpecification",
"price": "$200.00"
},
"paymentStatus": "payment due",
"provider": {
"#type": "Organization",
"name": "Acme Bank"
}
}
]
</script>
You should get this:
I marked up my email and sent it using the Gmail App Script tutorial.
<script type="application/ld+json">
{
"#context": "http://schema.org",
"#type": "EmailMessage",
"action": {
"#type": "ReviewAction",
"review": {
"#type": "Review",
"itemReviewed": {
"#type": "FoodEstablishment",
"name": "Joe's Diner"
},
"reviewRating": {
"#type": "Rating",
"bestRating": "5",
"worstRating": "1"
}
},
"handler": {
"#type": "HttpActionHandler",
"url": "http://gmail-demo-heroku-123.herokuapp.com/review",
"requiredProperty": {
"#type": "Property",
"name": "review.reviewRating.ratingValue"
},
"optionalProperty": {
"#type": "Property",
"name": "review.reviewBody"
},
"method": "http://schema.org/HttpRequestMethod/POST"
}
},
"description": "We hope you enjoyed your meal at Joe's Diner. Please tell us about it."
}
</script>
It shows up correctly in my inbox. It shows a review button. When I click on it it has a field for the body of the review and 5 stars that you can select. The Call To Action says publish on Gmail.com which is a little strange (and may point to the core issue), but I'm not sure.
When I click on the review button in Gmail and fill out the form, it provides the following error when I submit it.
Unable to send rating to gmail.com. Click on the stars again to retry.
The endpoint I provide can be reached and returns a 200 when I call it from console.
payload = {'review.reviewRating.ratingValue' : '2.0', 'review.reviewBody' : 'incredible'}
requests.post('http://gmail-demo-heroku-123.herokuapp.com/review',payload)
<Response [200]>
Why is Gmail giving this error? Is there a good way to debug this request coming from Gmail? Also, why is the Review Card saying Publish to Gmail.com in the Call To Action? The Schema.org markup appears to be correct in the email.