apps 0.2.1 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitignore +4 -0
- data/README.md +103 -19
- data/bin/setup +1 -2
- data/exe/apps +0 -0
- data/lib/apps/common/schema.rb +8 -0
- data/lib/apps/common/schema/base.rb +91 -0
- data/lib/apps/common/schema/concerns.rb +10 -0
- data/lib/apps/common/schema/concerns/potential_action.rb +35 -0
- data/lib/apps/gmail/markup.rb +158 -0
- data/lib/apps/gmail/schema.rb +21 -0
- data/lib/apps/gmail/schema/action.rb +19 -0
- data/lib/apps/gmail/schema/confirm_action.rb +21 -0
- data/lib/apps/gmail/schema/email_message.rb +15 -0
- data/lib/apps/gmail/schema/event.rb +41 -0
- data/lib/apps/gmail/schema/parcel_delivery.rb +43 -0
- data/lib/apps/gmail/schema/place.rb +24 -0
- data/lib/apps/gmail/schema/postal_address.rb +22 -0
- data/lib/apps/gmail/schema/rsvp_action.rb +25 -0
- data/lib/apps/gmail/schema/save_action.rb +20 -0
- data/lib/apps/gmail/schema/track_action.rb +20 -0
- data/lib/apps/gmail/schema/view_action.rb +20 -0
- data/lib/apps/outlook/actionable_messages.rb +13 -0
- data/lib/apps/outlook/schema.rb +20 -0
- data/lib/apps/outlook/schema/action.rb +14 -0
- data/lib/apps/outlook/schema/action_card.rb +42 -0
- data/lib/apps/outlook/schema/concerns.rb +14 -0
- data/lib/apps/outlook/schema/concerns/sections.rb +27 -0
- data/lib/apps/outlook/schema/concerns/sorted_potential_action.rb +17 -0
- data/lib/apps/outlook/schema/date_input.rb +17 -0
- data/lib/apps/outlook/schema/http_post.rb +44 -0
- data/lib/apps/outlook/schema/input.rb +23 -0
- data/lib/apps/outlook/schema/invoke_add_in_command.rb +33 -0
- data/lib/apps/outlook/schema/message_card.rb +39 -0
- data/lib/apps/outlook/schema/multichoice_input.rb +32 -0
- data/lib/apps/outlook/schema/open_uri.rb +24 -0
- data/lib/apps/outlook/schema/section.rb +52 -0
- data/lib/apps/outlook/schema/text_input.rb +20 -0
- data/lib/apps/version.rb +4 -1
- data/lib/examples.rb +121 -0
- data/package.json +12 -0
- metadata +37 -16
- data/lib/apps/adapters/gmail/markup.rb +0 -42
- data/lib/apps/adapters/gmail/markup/action.rb +0 -23
- data/lib/apps/adapters/gmail/markup/base.rb +0 -37
- data/lib/apps/adapters/gmail/markup/base_context.rb +0 -23
- data/lib/apps/adapters/gmail/markup/confirm_action.rb +0 -23
- data/lib/apps/adapters/gmail/markup/email_message.rb +0 -22
- data/lib/apps/adapters/gmail/markup/event.rb +0 -40
- data/lib/apps/adapters/gmail/markup/parcel_delivery.rb +0 -47
- data/lib/apps/adapters/gmail/markup/place.rb +0 -27
- data/lib/apps/adapters/gmail/markup/postal_address.rb +0 -26
- data/lib/apps/adapters/gmail/markup/rsvp_action.rb +0 -27
- data/lib/apps/adapters/gmail/markup/save_action.rb +0 -22
- data/lib/apps/adapters/gmail/markup/track_action.rb +0 -24
- data/lib/apps/adapters/gmail/markup/view_action.rb +0 -24
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 76c0dd94631910ba52d822088647ffbe60838983b938472cb3d94d006e632720
|
4
|
+
data.tar.gz: 9001b062a90772948b2472bf08ca3ce4e1cdb58d74a590c08a67bed9e91d23b6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: '058630fac77f03e0e9feb6b8648ad1809b8ba8de5990ae9323be349c16aad07734c153626180237e81013c920bcb4cca8fa98afb760738c13ce7214d20294dbd'
|
7
|
+
data.tar.gz: e937dcfa758a607370a5548eff21772f77c21c7445542b3a81e8225da497f689d355e27ee1d7ebafcb9724dd1a0606813fb25164443dec39fd1a386b518e98a6
|
data/.gitignore
CHANGED
data/README.md
CHANGED
@@ -4,9 +4,9 @@ This is a toolkit to easily integrate into platform marketplaces and extension p
|
|
4
4
|
|
5
5
|
The Apps gem is currently under development, with the goal of facilitating the following:
|
6
6
|
|
7
|
-
*
|
8
|
-
* [
|
9
|
-
* [
|
7
|
+
* Gmail
|
8
|
+
* [Add-ons](https://developers.google.com/gmail/add-ons/)
|
9
|
+
* [Email Markup](https://developers.google.com/gmail/markup/)
|
10
10
|
* AMP Pages
|
11
11
|
* Microsoft Office 365
|
12
12
|
* [Outlook Add-ins](https://docs.microsoft.com/en-us/outlook/add-ins/)
|
@@ -14,8 +14,8 @@ The Apps gem is currently under development, with the goal of facilitating the f
|
|
14
14
|
* Slack
|
15
15
|
* Bots
|
16
16
|
* Commands
|
17
|
-
* Heroku
|
18
|
-
*
|
17
|
+
* Heroku Elements Marketplace
|
18
|
+
* [Add-ons](https://devcenter.heroku.com/articles/building-an-add-on)
|
19
19
|
* Facebook
|
20
20
|
* Instant Articles
|
21
21
|
|
@@ -39,20 +39,75 @@ Or install it yourself as:
|
|
39
39
|
|
40
40
|
### Gmail Email Markup
|
41
41
|
|
42
|
-
You can generate [schema.org](http://schema.org) markup for email in Gmail utilizing simple helper classes.
|
43
|
-
|
44
|
-
*
|
45
|
-
*
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
42
|
+
You can generate [schema.org](http://schema.org) markup for email in Gmail utilizing simple helper classes. Use the helper methods in `Apps::Gmail::Markup` to easily define your markup.
|
43
|
+
|
44
|
+
* [Confirm Action](https://developers.google.com/gmail/markup/reference/one-click-action)
|
45
|
+
* [Save Action](https://developers.google.com/gmail/markup/reference/one-click-action)
|
46
|
+
* [RSVP Action](https://developers.google.com/gmail/markup/reference/rsvp-action)
|
47
|
+
* [View Action](https://developers.google.com/gmail/markup/reference/go-to-action)
|
48
|
+
* [Track Action](https://developers.google.com/gmail/markup/reference/go-to-action)
|
49
|
+
|
50
|
+
Explore `Apps::Gmail::Markup` and related classes to see how you can customize your metadata.
|
51
|
+
|
52
|
+
```ruby
|
53
|
+
require 'apps/gmail/markup'
|
54
|
+
|
55
|
+
# Confirm Action (takes additional keyword options)
|
56
|
+
confirm_action = Apps::Gmail::Markup.confirm_action('Button Text', 'http://example.org/confirm/endpoint')
|
57
|
+
|
58
|
+
confirm_action.as_json
|
59
|
+
# => {"@context"=>"http://schema.org", "@type"=>"EmailMessage", "potentialAction"=>{"@type"=>"ConfirmAction", "handler"=>{"@type"=>"HttpActionHandler", "url"=>"http://example.org/confirm/endpoint"}}}
|
60
|
+
|
61
|
+
puts confirm_action.to_json
|
62
|
+
# => {"@context":"http://schema.org","@type":"EmailMessage","potentialAction":{"@type":"ConfirmAction","handler":{"@type":"HttpActionHandler","url":"http://example.org/confirm/endpoint"}}}
|
63
|
+
|
64
|
+
# NOTE: `to_script` is only available on "context" objects that represent the root of the markup
|
65
|
+
# needed for embedding in emails. This is the object returned by each of the helper methods
|
66
|
+
# above for each "Action"
|
67
|
+
puts confirm_action.to_script
|
68
|
+
# =>
|
69
|
+
# <script type="application/ld+json">
|
70
|
+
# {
|
71
|
+
# "@context": "http://schema.org",
|
72
|
+
# "@type": "EmailMessage",
|
73
|
+
# "potentialAction": {
|
74
|
+
# "@type": "ConfirmAction",
|
75
|
+
# "handler": {
|
76
|
+
# "@type": "HttpActionHandler",
|
77
|
+
# "url": "http://example.org/confirm/endpoint"
|
78
|
+
# }
|
79
|
+
# }
|
80
|
+
# }
|
81
|
+
# </script>
|
82
|
+
|
83
|
+
# Save Action (takes additional keyword options)
|
84
|
+
save_action = Apps::Gmail::Markup.save_action('Button Text', 'http://example.org/save/endpoint')
|
85
|
+
|
86
|
+
# RSVP Action (takes additional keyword options)
|
87
|
+
rsvp_action = Apps::Gmail::Markup.rsvp_action('Event Name',
|
88
|
+
yes_url: 'http://example.org/yes/endpoint',
|
89
|
+
no_url: 'http://example.org/no/endpoint',
|
90
|
+
maybe_url: 'http://example.org/maybe/endpoint'
|
91
|
+
)
|
92
|
+
|
93
|
+
# View Action (takes additional keyword options)
|
94
|
+
view_action = Apps::Gmail::Markup.view_action('Button Text', 'http://example.org/save/endpoint')
|
95
|
+
|
96
|
+
# Track Action (takes additional keyword options)
|
97
|
+
track_action = Apps::Gmail::Markup.track_action('Button Text', 'http://example.org/save/endpoint')
|
98
|
+
```
|
99
|
+
|
100
|
+
You need to [register with Google](https://developers.google.com/gmail/markup/registering-with-google) to get your actions approved.
|
101
|
+
|
102
|
+
**Related Resoures:**
|
103
|
+
|
104
|
+
* [Embeding JSON-LD in HTML Documents](https://json-ld.org/spec/latest/json-ld/#embedding-json-ld-in-html-documents)
|
105
|
+
* [Test Your Schemas](https://developers.google.com/gmail/markup/testing-your-schema)
|
106
|
+
* [Email Markup Tester](https://www.google.com/webmasters/markup-tester/)
|
107
|
+
* [Structured Data Markup Helper](https://www.google.com/webmasters/markup-helper/?email=true)
|
108
|
+
* [Register with Google](https://developers.google.com/gmail/markup/registering-with-google)
|
109
|
+
* Articles:
|
110
|
+
* [A Guide to Setting up Gmail Inbox Actions](http://blog.meldium.com/home/2014/5/19/setting-up-gmail-inbox-actions) by Meldium
|
56
111
|
|
57
112
|
#### TODO
|
58
113
|
|
@@ -60,6 +115,35 @@ You can generate [schema.org](http://schema.org) markup for email in Gmail utili
|
|
60
115
|
* Email Markup helpers for other Gmail-supported metadata need to be implemented
|
61
116
|
* Additional Gmail integrations need to be developed
|
62
117
|
|
118
|
+
### Microsoft Office 365
|
119
|
+
|
120
|
+
* [Office Developer](https://github.com/OfficeDev) - git repositories of example projects for Outlook Add-ins, etc.
|
121
|
+
* [Yeoman generator](https://github.com/OfficeDev/generator-office) - generator for creating [Microsoft office Add-ins](https://docs.microsoft.com/en-us/office/dev/add-ins/)
|
122
|
+
* [Message Card Playground](https://messagecardplayground.azurewebsites.net/) - test schema.org markup and how it generates add-in UI
|
123
|
+
|
124
|
+
#### Outlook: Actionable Messages via Email
|
125
|
+
|
126
|
+
All Actionable Card markup schemas supported by Microsoft Office are implemented in this library (see [Actionable message card reference](https://docs.microsoft.com/en-us/outlook/actionable-messages/card-reference)).
|
127
|
+
|
128
|
+
```ruby
|
129
|
+
require 'apps/outlook/actionable_messages'
|
130
|
+
|
131
|
+
message_card = Apps::Outlook::ActionableMessages.message_card('Summary text', 'Title text')
|
132
|
+
```
|
133
|
+
|
134
|
+
You can take a look at (and run) [lib/examples.rb](./lib/examples.rb) to see some sample markup.
|
135
|
+
|
136
|
+
$ ruby lib/examples.rb
|
137
|
+
|
138
|
+
You can get more example schemas or copy/paste the output of `examples.rb` to test rendering here: https://messagecardplayground.azurewebsites.net/
|
139
|
+
|
140
|
+
**Related Resources:**
|
141
|
+
|
142
|
+
* [Actionable Messages via Email](https://docs.microsoft.com/en-us/outlook/actionable-messages/actionable-messages-via-email)
|
143
|
+
* [Actionable message card reference](https://docs.microsoft.com/en-us/outlook/actionable-messages/card-reference)
|
144
|
+
* [Register your service with the actionable email developer dashboard](https://docs.microsoft.com/en-us/outlook/actionable-messages/actionable-email-dev-dashboard)
|
145
|
+
* [Register your connector with the Office 365 Connectors developer dashboard](https://docs.microsoft.com/en-us/outlook/actionable-messages/connectors-dev-dashboard) - setup a connector for users to authorize your add-in
|
146
|
+
|
63
147
|
## Development
|
64
148
|
|
65
149
|
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
data/bin/setup
CHANGED
data/exe/apps
CHANGED
File without changes
|
@@ -0,0 +1,91 @@
|
|
1
|
+
require 'json'
|
2
|
+
|
3
|
+
module Apps
|
4
|
+
module Common
|
5
|
+
module Schema
|
6
|
+
class Base
|
7
|
+
DEFAULT_CONTEXT = 'http://schema.org'
|
8
|
+
|
9
|
+
attr_reader :context, # the schema.org URL if not the default
|
10
|
+
:force_context # force including the default schema.org context if none specified
|
11
|
+
|
12
|
+
def initialize(**attrs)
|
13
|
+
prune(attrs).each { |name, value| instance_variable_set(:"@#{name}", value) }
|
14
|
+
end
|
15
|
+
|
16
|
+
def type
|
17
|
+
@type ||= self.class.name.split('::')[-1]
|
18
|
+
end
|
19
|
+
|
20
|
+
def serialize
|
21
|
+
{
|
22
|
+
"@context" => serialized_context,
|
23
|
+
"@type" => type
|
24
|
+
}
|
25
|
+
end
|
26
|
+
|
27
|
+
def serialize_hash(hash, key: 'name', value: 'value')
|
28
|
+
hash.map do |k, v|
|
29
|
+
{
|
30
|
+
key => k,
|
31
|
+
value => v
|
32
|
+
}
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def serialized_context
|
37
|
+
if force_context
|
38
|
+
context || DEFAULT_CONTEXT
|
39
|
+
else
|
40
|
+
context
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def as_json(force_context: false)
|
45
|
+
serialized = serialize
|
46
|
+
|
47
|
+
if force_context == true
|
48
|
+
serialized['@context'] ||= DEFAULT_CONTEXT
|
49
|
+
elsif force_context.is_a?(String)
|
50
|
+
serialized['@context'] = force_context
|
51
|
+
end
|
52
|
+
|
53
|
+
prune serialized
|
54
|
+
end
|
55
|
+
|
56
|
+
def to_json(force_context: false, pretty: false)
|
57
|
+
hash = as_json(force_context: force_context)
|
58
|
+
|
59
|
+
pretty ? JSON.pretty_generate(hash) : JSON.dump(hash)
|
60
|
+
end
|
61
|
+
|
62
|
+
def to_script(force_context: false, pretty: true)
|
63
|
+
json = to_json(pretty: pretty, force_context: force_context)
|
64
|
+
|
65
|
+
%`<script type="application/ld+json">\n#{json}\n</script>`
|
66
|
+
end
|
67
|
+
|
68
|
+
protected
|
69
|
+
|
70
|
+
def prune(hash)
|
71
|
+
hash.each_with_object({}) do |(key, value), result|
|
72
|
+
# recursive prune
|
73
|
+
result[key] = case value
|
74
|
+
when nil
|
75
|
+
next
|
76
|
+
when Array
|
77
|
+
next if value.empty?
|
78
|
+
value.map{ |v| v.is_a?(Hash) ? prune(v) : v }
|
79
|
+
when Hash
|
80
|
+
value = prune value
|
81
|
+
next if value.empty?
|
82
|
+
value
|
83
|
+
else
|
84
|
+
value
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Apps
|
2
|
+
module Common
|
3
|
+
module Schema
|
4
|
+
module Concerns
|
5
|
+
module PotentialAction
|
6
|
+
# Handles the case when there is one action
|
7
|
+
def action
|
8
|
+
actions.first if actions.size == 1
|
9
|
+
end
|
10
|
+
|
11
|
+
def actions
|
12
|
+
@actions ||= [@action].compact
|
13
|
+
end
|
14
|
+
|
15
|
+
def serialize
|
16
|
+
if actions.any?
|
17
|
+
super.merge("potentialAction" => serialize_actions)
|
18
|
+
else
|
19
|
+
super
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def serialize_actions
|
24
|
+
# Gmail uses a hash for one action and an array for multiple.
|
25
|
+
# Outlook uses an array regardless and breaks if it's a hash.
|
26
|
+
# So we will always return an array.
|
27
|
+
|
28
|
+
# action&.serialize || actions.map(&:serialize)
|
29
|
+
actions.map(&:serialize)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,158 @@
|
|
1
|
+
require_relative 'schema'
|
2
|
+
|
3
|
+
module Apps
|
4
|
+
module Gmail
|
5
|
+
module Markup
|
6
|
+
class << self
|
7
|
+
# {
|
8
|
+
# "@context": "http://schema.org",
|
9
|
+
# "@type": "EmailMessage",
|
10
|
+
# "potentialAction": {
|
11
|
+
# "@type": "ConfirmAction",
|
12
|
+
# "handler": {
|
13
|
+
# "@type": "HttpActionHandler",
|
14
|
+
# "url": "https://example.org/confirm/endpoint"
|
15
|
+
# },
|
16
|
+
# "name": "Action Name"
|
17
|
+
# }
|
18
|
+
# }
|
19
|
+
def confirm_action(name, url, **attrs)
|
20
|
+
action = Schema::ConfirmAction.new(name: name, url: url)
|
21
|
+
root = Schema::EmailMessage.new(action: action, **attrs)
|
22
|
+
|
23
|
+
root
|
24
|
+
end
|
25
|
+
|
26
|
+
# {
|
27
|
+
# "@context": "http://schema.org",
|
28
|
+
# "@type": "EmailMessage",
|
29
|
+
# "potentialAction": {
|
30
|
+
# "@type": "SaveAction",
|
31
|
+
# "handler": {
|
32
|
+
# "@type": "HttpActionHandler",
|
33
|
+
# "url": "https://example.org/save/endpoint"
|
34
|
+
# },
|
35
|
+
# "name": "Action Name"
|
36
|
+
# }
|
37
|
+
# }
|
38
|
+
def save_action(name, url, **attrs)
|
39
|
+
action = Schema::SaveAction.new(name: name, url: url)
|
40
|
+
root = Schema::EmailMessage.new(action: action, **attrs)
|
41
|
+
|
42
|
+
root
|
43
|
+
end
|
44
|
+
|
45
|
+
# {
|
46
|
+
# "@context": "http://schema.org",
|
47
|
+
# "@type": "Event",
|
48
|
+
# "name": "Action Name",
|
49
|
+
# "location": {
|
50
|
+
# "@type": "Place",
|
51
|
+
# "address": {
|
52
|
+
# "@type": "PostalAddress"
|
53
|
+
# }
|
54
|
+
# },
|
55
|
+
# "potentialAction": [
|
56
|
+
# {
|
57
|
+
# "@type": "RsvpAction",
|
58
|
+
# "handler": {
|
59
|
+
# "@type": "HttpActionHandler",
|
60
|
+
# "url": "http://example.org/yes/endpoint"
|
61
|
+
# },
|
62
|
+
# "rsvpResponse": "yes",
|
63
|
+
# "attendance": "http://schema.org/RsvpAttendance/Yes"
|
64
|
+
# },
|
65
|
+
# {
|
66
|
+
# "@type": "RsvpAction",
|
67
|
+
# "handler": {
|
68
|
+
# "@type": "HttpActionHandler",
|
69
|
+
# "url": "http://example.org/no/endpoint"
|
70
|
+
# },
|
71
|
+
# "rsvpResponse": "no",
|
72
|
+
# "attendance": "http://schema.org/RsvpAttendance/No"
|
73
|
+
# },
|
74
|
+
# {
|
75
|
+
# "@type": "RsvpAction",
|
76
|
+
# "handler": {
|
77
|
+
# "@type": "HttpActionHandler",
|
78
|
+
# "url": "http://example.org/maybe/endpoint"
|
79
|
+
# },
|
80
|
+
# "rsvpResponse": "maybe",
|
81
|
+
# "attendance": "http://schema.org/RsvpAttendance/Maybe"
|
82
|
+
# }
|
83
|
+
# ]
|
84
|
+
# }
|
85
|
+
def rsvp_action(name, yes_url: nil, no_url: nil, maybe_url: nil, **attrs)
|
86
|
+
Schema::Event.new(name: name, **attrs).tap do |root|
|
87
|
+
root.build_location unless root.location
|
88
|
+
root.build_rsvp_actions unless root.actions.any?
|
89
|
+
|
90
|
+
responses = {
|
91
|
+
'Yes' => yes_url,
|
92
|
+
'No' => no_url,
|
93
|
+
'Maybe' => maybe_url
|
94
|
+
}
|
95
|
+
|
96
|
+
# Specify RSVP URLs
|
97
|
+
responses.each do |response, url|
|
98
|
+
next if url.nil?
|
99
|
+
|
100
|
+
action = root.actions.find { |action| action.response == response }
|
101
|
+
action ||= root.add_action_for(response)
|
102
|
+
|
103
|
+
action.url = url
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
# {
|
109
|
+
# "@context": "http://schema.org",
|
110
|
+
# "@type": "EmailMessage",
|
111
|
+
# "potentialAction": {
|
112
|
+
# "@type": "ViewAction",
|
113
|
+
# "name": "Action Name",
|
114
|
+
# "target": "http://example.org/view/endpoint"
|
115
|
+
# }
|
116
|
+
# }
|
117
|
+
def view_action(name, target, **attrs)
|
118
|
+
action = Schema::ViewAction.new(name: name, target: target)
|
119
|
+
root = Schema::EmailMessage.new(action: action, **attrs)
|
120
|
+
|
121
|
+
root
|
122
|
+
end
|
123
|
+
|
124
|
+
# {
|
125
|
+
# "@context": "http://schema.org",
|
126
|
+
# "@type": "ParcelDelivery",
|
127
|
+
# "deliveryAddress": {
|
128
|
+
# "@type": "PostalAddress"
|
129
|
+
# },
|
130
|
+
# "carrier": {
|
131
|
+
# "@type": "Organization"
|
132
|
+
# },
|
133
|
+
# "itemShipped": {
|
134
|
+
# "@type": "Product"
|
135
|
+
# },
|
136
|
+
# "partOfOrder": {
|
137
|
+
# "@type": "Order",
|
138
|
+
# "merchant": {
|
139
|
+
# "@type": "Organization"
|
140
|
+
# }
|
141
|
+
# },
|
142
|
+
# "potentialAction": {
|
143
|
+
# "@type": "TrackAction",
|
144
|
+
# "name": "Action Name",
|
145
|
+
# "target": "https://example.org/track/endpoint"
|
146
|
+
# }
|
147
|
+
# }
|
148
|
+
def track_action(name, target, **attrs)
|
149
|
+
action = Schema::TrackAction.new(name: name, target: target)
|
150
|
+
|
151
|
+
Schema::ParcelDelivery.new(action: action, **attrs).tap do |root|
|
152
|
+
root.build_delivery_address unless root.delivery_address
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|