GoodRelationsPricing
From Wiki of the E-Business and Web Science Research Group
|
| GoodRelations is a standardized vocabulary for product, price, and company data that can be embedded into existing static and dynamic Web pages. |
|---|
|
Project Main Page |
Contents |
Overview
This page describes how the GoodRelations ontology for e-commerce can be used to model price information. Such can be embedded using the W3C RDFa syntax into Web pages and will be crawled and used by next generation Web search engines.
One of the design principles of GoodRelations (*) is that
- simple things should be simple to express, while
- complex things should be possible to model without tweaking or extending the vocabulary.
On this page, we demonstrate how the established GoodRelations elements can be used to expose fine-granular price information like
"We lease our boats for 24 USD per 6 hours for 0-3 days, and for 75 USD per day for any longer rental."
(*) Wikiquote attributes this principle to Alan Kay.
Exposing GoodRelations rich meta-data can be as simple as this:
Minimal Example: Turtle Syntax
@prefix gr: <http://purl.org/goodrelations/v1#> . @prefix xsd: <http://www.w3.org/2001/XMLSchema#> . @prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> . :company a gr:BusinessEntity; gr:legalName "Hepp Space Ventures Inc."@en; gr:offers :offering. :offering a gr:Offering; rdfs:label "Volkswagen Station Wagon, 4WD, 400 $"@en; rdfs:comment "I sell my old Volkswagen Station Wagon, 4WD, for 400 $"@en; gr:hasBusinessFunction gr:Sell; gr:hasPriceSpecification [ a gr:UnitPriceSpecification; gr:hasCurrencyValue "400"^^xsd:float; gr:hasCurrency "USD"^^xsd:string. ].
Minimal Example: RDFa Syntax
<div xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#" xmlns="http://www.w3.org/1999/xhtml" xmlns:gr="http://purl.org/goodrelations/v1#" xmlns:xsd="http://www.w3.org/2001/XMLSchema#"> <div about="#company" typeof="gr:BusinessEntity"> <div property="gr:legalName" content="Hepp Space Ventures Inc." xml:lang="en"></div> <div rel="gr:offers"> <div about="#offering" typeof="gr:Offering"> <div property="rdfs:comment" content="I sell my old Volkswagen Station Wagon, 4WD, for 400 $" xml:lang="en"></div> <div rel="gr:hasBusinessFunction" resource="http://purl.org/goodrelations/v1#Sell"></div> <div rel="gr:hasPriceSpecification"> <div typeof="gr:UnitPriceSpecification"> <div property="gr:hasCurrency" content="USD" datatype="xsd:string"></div> <div property="gr:hasCurrencyValue" content="400" datatype="xsd:float"></div> </div> </div> <div property="rdfs:label" content="Volkswagen Station Wagon, 4WD, 400 $" xml:lang="en"></div> </div> </div> </div> </div>
But when you have more fine-grained data available on your end, you will likely expose that full level of detail on the Web.
Preliminaries
Prefixes
First, we have to define the prefixes used in the examples:
@prefix foo: <http://www.example.com/xyz#> . @prefix gr: <http://purl.org/goodrelations/v1#> . @prefix xsd: <http://www.w3.org/2001/XMLSchema#> . @prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
Simple Offer
Next, let's model a simple offer to sell potatoes.
# Offer to sell potatoes foo:company a gr:BusinessEntity ; gr:legalName "Hepp Space Ventures, Inc."@en ; gr:offers foo:offer. foo:offer a gr:Offering ; rdfs:label "Potatoes for sale"@en ; rdfs:comment "We sell potatoes"@en ; gr:hasBusinessFunction gr:Sell ; gr:validFrom "2010-05-01T00:00:00Z"^^xsd:dateTime ; gr:validThrough "2010-12-31T23:59:59Z"^^xsd:dateTime ; gr:hasPriceSpecification foo:price.
Note: The actual object being offered (i.e. the potatoes) can (and should) be described in more detail. See the other GoodRelations recipes for examples. This recipe focuses on modeling the pricing.
Pricing
Example: 1 USD per piece
The UN/CEFACT Common Code for "piece" or "item" is "C62".
# 1 USD per piece (= per potatoe) foo:price a gr:UnitPriceSpecification ; gr:hasCurrency "USD"^^xsd:string ; gr:hasCurrencyValue "1.0"^^xsd:float ; gr:hasUnitOfMeasurement "C62"^^xsd:string ; gr:valueAddedTaxIncluded "true"^^xsd:boolean .
Example: 4 USD per kilogram
The UN/CEFACT Common Code for "kilogram" is "KGM" .
# 4 USD per kilogram foo:price a gr:UnitPriceSpecification ; gr:hasCurrency "USD"^^xsd:string ; gr:hasCurrencyValue "4.0"^^xsd:float ; gr:hasUnitOfMeasurement "KGM"^^xsd:string ; gr:valueAddedTaxIncluded "true"^^xsd:boolean .
Quantity Discounts
Simply attach multiple instances of gr:UnitPriceSpecification to the gr:Offering and constrain their validity using gr:hasEligibleQuantity and gr:hasUnitOfMeasurement.
# 4 USD per kilogram up to 5 kilogram, 3 USD for any quantity beyond that foo:price1 a gr:UnitPriceSpecification ; gr:hasCurrency "USD"^^xsd:string ; gr:hasCurrencyValue "4.0"^^xsd:float ; gr:hasUnitOfMeasurement "KGM"^^xsd:string ; gr:valueAddedTaxIncluded "true"^^xsd:boolean ; gr:hasEligibleQuantity [ a gr:QuantitativeValueInteger ; gr:hasUnitOfMeasurement "KGM"^^xsd:string ; gr:hasMinValueInteger "0"^^xsd:int ; gr:hasMaxValueInteger "5"^^xsd:int . ]. foo:price2 a gr:UnitPriceSpecification ; gr:hasCurrency "USD"^^xsd:string ; gr:hasCurrencyValue "3.0"^^xsd:float ; gr:hasUnitOfMeasurement "KGM"^^xsd:string ; gr:valueAddedTaxIncluded "true"^^xsd:boolean ; gr:hasEligibleQuantity [ a gr:QuantitativeValueInteger ; gr:hasUnitOfMeasurement "KGM"^^xsd:string ; gr:hasMinValueInteger "6"^^xsd:int . ].
You have to link from the offering to both price specifications now. Simply change
- gr:hasPriceSpecification foo:price.
to
- gr:hasPriceSpecification foo:price1, foo:price2.
So the offer node will look as follows:
foo:offer a gr:Offering; gr:includes foo:potatoes; gr:validFrom "2010-05-01T00:00:00Z"^^xsd:dateTime ; gr:validThrough "2010-12-31T23:59:59Z"^^xsd:dateTime ; gr:hasPriceSpecification foo:price1, foo:price2.
Seasonal Discounts and Special Offers
Simply attach multiple gr:UnitPriceSpecification instances to the gr:Offering and constrain their temporal validity using gr:validFrom and gr:validThrough.
Example: 4 USD per kilogram, 3 USD from May 1 - June 30, 2010
# 4 USD per kilogram from July 1 - December 31, 2010 foo:price1 a gr:UnitPriceSpecification ; gr:hasCurrency "USD"^^xsd:string ; gr:hasCurrencyValue "4.0"^^xsd:float ; gr:hasUnitOfMeasurement "KGM"^^xsd:string ; gr:valueAddedTaxIncluded "true"^^xsd:boolean ; gr:validFrom "2010-07-01T00:00:00Z"^^xsd:dateTime ; gr:validThrough "2010-12-31T23:59:59Z"^^xsd:dateTime . # 4 USD per kilogram from May 1 - June 30, 2010 foo:price2 a gr:UnitPriceSpecification ; gr:hasCurrency "USD"^^xsd:string ; gr:hasCurrencyValue "3.0"^^xsd:float ; gr:hasUnitOfMeasurement "KGM"^^xsd:string ; gr:valueAddedTaxIncluded "true"^^xsd:boolean ; gr:validFrom "2010-05-01T00:00:00Z"^^xsd:dateTime ; gr:validThrough "2010-06-30T23:59:59Z"^^xsd:dateTime .
Same as in the previous example, you have to link from the offering to both price specifications now.
Change
- gr:hasPriceSpecification foo:price.
to
- gr:hasPriceSpecification foo:price1, foo:price2.
Billing Increments
The property gr:billingIncrement with a domain of gr:UnitPriceSpecification and a range of xsd:float allows indicating the smallest billable unit of an item.
Examples:
- Price 2 euro per hour, billing in units of 15 minutes
- The price be 4 USD per kilogram of potatoes, but the billing will be based on the quantity rounded up to the next multiple of 100 grams.
The UN/CEFACT Common Code for "kilogram" is "KGM", that for gram is "GRM". Note that you have to use the same unit for the billing increment and the unit of measurement for the price reference, so either you express this as 4 USD per kilogram with an increment of 0.1 kilograms or as a price of 0.004 USD per gram with a billing increment of 100 grams.
# 4 USD per kilogram, billing increment 100 g foo:price a gr:UnitPriceSpecification; gr:hasCurrency "USD"^^xsd:string; gr:hasCurrencyValue "4.0"^^xsd:float; gr:hasUnitOfMeasurement "KGM"^^xsd:string; gr:valueAddedTaxIncluded "true"^^xsd:boolean ; gr:billingIncrement "0.1"^^xsd:float .
Important: The billing increment specifies only the rounding steps for determining the billable quantity. The price is given per unit of measurement. For instance, the example above expresses that the price is 4 USD per kilogram and not 4 USD per 0.1 kilograms.
Price Ranges
Sometimes, the price can only be given as an interval, depending on characteristics of the actual item or the buying party. Simply use gr:hasMaxCurrencyValue and gr:hasMinCurrencyValue for the upper and lower bounds instead of gr:hasCurrencyValue. An RDFS-style reasoner will expand gr:hasCurrencyValue to two matching gr:hasMinCurrencyValue and gr:hasMaxCurrencyValue statements anyway. When querying, you should process gr:hasMinCurrencyValue and gr:hasMaxCurrencyValue instead of gr:hasCurrencyValue, unless you want to ignore offers that give ranges only.
# 3..4 USD per kilogram, depending on the size of the potatoes foo:price a gr:UnitPriceSpecification ; gr:hasCurrency "USD"^^xsd:string ; gr:hasMinCurrencyValue "3.0"^^xsd:float ; gr:hasMaxCurrencyValue "4.0"^^xsd:float ; gr:hasUnitOfMeasurement "KGM"^^xsd:string ; gr:valueAddedTaxIncluded "true"^^xsd:boolean .
Indicating List Prices
You can indicate retails prices as recommended by the supplier etc. using the gr:priceType property. This attribute can be used to distinguish multiple different gr:UnitPriceSpecification instances for the same offer. It supersedes the former gr: isListPrice property. The following values are recommended:
- SRP: "suggested retail price" - applicable for all sorts of a non-binding retail price recommendations, e.g. such published by the manufacturer or the distributor. This value replaces the former gr:isListPrice property.
- INVOICE: The invoice price, mostly used in the car industry - this is the price a dealer pays to the manufacturer, excluding rebates and charges.
The absence of this property marks the actual sales price.
# 4 USD per kilogram with a "suggested retail price" of 4.50 USD. foo:price1 a gr:UnitPriceSpecification ; gr:hasCurrency "USD"^^xsd:string ; gr:hasCurrencyValue "4.0"^^xsd:float ; gr:hasUnitOfMeasurement "KGM"^^xsd:string ; gr:valueAddedTaxIncluded "true"^^xsd:boolean . foo:price2 a gr:UnitPriceSpecification ; gr:hasCurrency "USD"^^xsd:string ; gr:hasCurrencyValue "4.5"^^xsd:float ; gr:hasUnitOfMeasurement "KGM"^^xsd:string ; gr:valueAddedTaxIncluded "true"^^xsd:boolean ; gr: priceType "SRP"^^xsd:string .
Car Rental: 25 USD / day plus 1 USD per mile
You can combine multiple gr:UnitPriceSpecification instances that are valid in combination. For example, a rental car business might say that the price for a particular rental car is 25 USD per day plus 1 USD per mile.
Note that the UN/CEFACT Common Code for "day" is "DAY", that for "car mile" is "1A". Also note that the gr:BusinessFunction for rental is gr:LeaseOut.
# Car Rental: 25 USD / day, 1 USD per mile foo:company a gr:BusinessEntity ; gr:legalName "Hepp Space Ventures, Inc."@en ; gr:offers foo:car_offer. foo:car_offer a gr:Offering ; rdfs:label "Car rental"@en ; rdfs:comment "We rent out cars"@en ; gr:hasBusinessFunction gr:LeaseOut ; gr:hasPriceSpecification foo:rental_price1, foo:rental_price2 . foo:rental_price1 a gr:UnitPriceSpecification ; gr:hasCurrency "USD"^^xsd:string ; gr:hasCurrencyValue "25"^^xsd:float ; gr:hasUnitOfMeasurement "DAY"^^xsd:string ; gr:valueAddedTaxIncluded "true"^^xsd:boolean . foo:rental_price2 a gr:UnitPriceSpecification ; gr:hasCurrency "USD"^^xsd:string ; gr:hasCurrencyValue "1"^^xsd:float ; gr:hasUnitOfMeasurement "1A"^^xsd:string ; gr:valueAddedTaxIncluded "true"^^xsd:boolean .
Note: The vehicles being offered can (and should) be described in more detail. See the other GoodRelations recipes for examples. This recipe focuses on modeling the pricing.
Cancellation Rules
GoodRelations does not provide a means for modeling cancellation policies and fees in detail, but you can easily attach them using
rdfs:comment
to the gr:UnitPriceSpecification node.
foo:rental_price a gr:UnitPriceSpecification ;
gr:hasCurrency "USD"^^xsd:string ;
gr:hasCurrencyValue "75"^^xsd:float ;
gr:hasUnitOfMeasurement "DAY"^^xsd:string ;
gr:valueAddedTaxIncluded "true"^^xsd:boolean ;
rdfs:comment "Cancellation Policy: You can cancel free of charge up to 72 hours prior to the start of the lease.
In case of any later cancellation, we will charge the rental fees for one day."@en.
Complex Examples
Boat Rental: 100 USD / day 0-3 days, 75 USD per day for any longer rental
Turtle Syntax
# Boat Rental: 100 USD / day 0-3 days, 75 USD per day for any longer rental foo:company a gr:BusinessEntity ; gr:legalName "Hepp Space Ventures, Inc."@en ; gr:offers foo:boat_offer. foo:boat_offer a gr:Offering ; rdfs:label "Boat rental"@en ; rdfs:comment "We rent out boats"@en ; gr:hasBusinessFunction gr:LeaseOut ; gr:hasPriceSpecification foo:rental_price1, foo:rental_price2 . foo:rental_price1 a gr:UnitPriceSpecification ; gr:hasCurrency "USD"^^xsd:string ; gr:hasCurrencyValue "100"^^xsd:float ; gr:hasUnitOfMeasurement "DAY"^^xsd:string ; gr:valueAddedTaxIncluded "true"^^xsd:boolean ; gr:hasEligibleQuantity [ a gr:QuantitativeValueInteger ; gr:hasUnitOfMeasurement "DAY"^^xsd:string ; gr:hasMinValueInteger "0"^^xsd:int ; gr:hasMaxValueInteger "3"^^xsd:int . ]. foo:rental_price2 a gr:UnitPriceSpecification ; gr:hasCurrency "USD"^^xsd:string ; gr:hasCurrencyValue "75"^^xsd:float ; gr:hasUnitOfMeasurement "DAY"^^xsd:string ; gr:valueAddedTaxIncluded "true"^^xsd:boolean ; gr:hasEligibleQuantity [ a gr:QuantitativeValueInteger ; gr:hasUnitOfMeasurement "DAY"^^xsd:string ; gr:hasMinValueInteger "4"^^xsd:int . ].
RDFa Syntax
<div xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#" xmlns="http://www.w3.org/1999/xhtml" xmlns:gr="http://purl.org/goodrelations/v1#" xmlns:foo="http://www.example.com/xyz#" xmlns:xsd="http://www.w3.org/2001/XMLSchema#" > <div about="http://www.example.com/xyz#company" typeof="gr:BusinessEntity"> <div property="gr:legalName" content="Hepp Space Ventures, Inc." xml:lang="en"></div> <div rel="gr:offers"> <div about="http://www.example.com/xyz#boat_offer" typeof="gr:Offering"> <div property="rdfs:comment" content="We rent out boats" xml:lang="en"></div> <div rel="gr:hasBusinessFunction" resource="http://purl.org/goodrelations/v1#LeaseOut"></div> <div rel="gr:hasPriceSpecification"> <div about="http://www.example.com/xyz#rental_price2" typeof="gr:UnitPriceSpecification"> <div property="gr:hasCurrency" content="USD" datatype="xsd:string"></div> <div property="gr:hasCurrencyValue" content="75" datatype="xsd:float"></div> <div rel="gr:hasEligibleQuantity"> <div typeof="gr:QuantitativeValueInteger"> <div property="gr:hasMinValueInteger" content="4" datatype="xsd:int"></div> <div property="gr:hasUnitOfMeasurement" content="DAY" datatype="xsd:string"></div> </div> </div> <div property="gr:hasUnitOfMeasurement" content="DAY" datatype="xsd:string"></div> <div property="gr:valueAddedTaxIncluded" content="true" datatype="xsd:boolean"></div> </div> </div> <div rel="gr:hasPriceSpecification"> <div about="http://www.example.com/xyz#rental_price1" typeof="gr:UnitPriceSpecification"> <div property="gr:hasCurrency" content="USD" datatype="xsd:string"></div> <div property="gr:hasCurrencyValue" content="100" datatype="xsd:float"></div> <div rel="gr:hasEligibleQuantity"> <div typeof="gr:QuantitativeValueInteger"> <div property="gr:hasMaxValueInteger" content="3" datatype="xsd:int"></div> <div property="gr:hasMinValueInteger" content="0" datatype="xsd:int"></div> <div property="gr:hasUnitOfMeasurement" content="DAY" datatype="xsd:string"></div> </div> </div> <div property="gr:hasUnitOfMeasurement" content="DAY" datatype="xsd:string"></div> <div property="gr:valueAddedTaxIncluded" content="true" datatype="xsd:boolean"></div> </div> </div> <div property="rdfs:label" content="Boat rental" xml:lang="en"></div> </div> </div> </div> </div>
Boat Rental: 24 USD / 6 hours for 0-3 days, 75 USD per day for any longer rental
Note that the price information "24 USD per 6 hours" must be translated into 24/6 = 4 USD per hour and a billing increment of 6.0 hours. The UN/CEFACT Common Code for "hour" is "HUR".
# Boat Rental: 24 USD / 6 hours for 0-3 days, 75 USD per day for any longer rental foo:rental_price1 a gr:UnitPriceSpecification ; gr:hasCurrency "USD"^^xsd:string ; # 24 USD per 6 hours => 4 USD / hour gr:hasCurrencyValue "4"^^xsd:float ; gr:hasUnitOfMeasurement "HUR"^^xsd:string ; gr:billingIncrement "6"^^xsd:float gr:valueAddedTaxIncluded "true"^^xsd:boolean ; gr:hasEligibleQuantity [ a gr:QuantitativeValueInteger ; gr:hasUnitOfMeasurement "DAY"^^xsd:string ; gr:hasMinValueInteger "0"^^xsd:int ; gr:hasMaxValueInteger "3"^^xsd:int . ]. foo:rental_price2 a gr:UnitPriceSpecification ; gr:hasCurrency "USD"^^xsd:string ; gr:hasCurrencyValue "75"^^xsd:float ; gr:hasUnitOfMeasurement "DAY"^^xsd:string ; gr:valueAddedTaxIncluded "true"^^xsd:boolean ; gr:hasEligibleQuantity [ a gr:QuantitativeValueInteger ; gr:hasUnitOfMeasurement "DAY"^^xsd:string ; gr:hasMinValueInteger "4"^^xsd:int . ].

