diff --git a/index.bs b/index.bs
new file mode 100644
index 0000000..f092e6c
--- /dev/null
+++ b/index.bs
@@ -0,0 +1,362 @@
+
+Title: Page Unload Beacon
+Status: UD
+ED: http://wicg.github.io/unload-beacon/
+Shortname: unload-beacon
+Level: 1
+Editor: Ian Clelland, Google
+Abstract: This document introduces an API for registering data to be sent to a predetermined server
+ at the point that a page is unloaded.
+Group: WebPerf
+Repository: WICG/unload-beacon
+
+
+Introduction {#introduction}
+============================
+
+This is an introduction.
+
+Issue: This introduction needs to be more of an introduction.
+
+Pending Beacon Framework {#pending-beacon-framework}
+====================================================
+
+Concepts {#concepts}
+--------------------
+
+A pending beacon represents a piece of data which has been
+registered with the user agent for later sending to an origin server.
+
+A [=pending beacon=] has a url, which is a
+[=/URL=].
+
+A [=pending beacon=] has a method, which is a
+string, which is initally "POST".
+
+A [=pending beacon=] has a timeout, which is
+either null or an integer, and which is initially null.
+
+A [=pending beacon=] has an is_pending flag,
+which is a [=boolean=], which is initially true.
+
+A [=pending beacon=] has a payload, which is a
+[=byte sequence=]. It is initially empty.
+
+A [=Document=] has a pending beacon set, which is an
+[=ordered set=] of [=pending beacons=].
+
+Issue: Add worker beacons as well?
+
+Note: In this spec, the [=pending beacon set=] is associated with a [=Document=].
+In an actual implementation, this set will likely need to be stored in the user
+agent, separate from the document itself, in order to be able to send beacons
+when the document is destroyed (either by being unloaded, or because of a crash).
+
+Issue: Define these to be part of the user agent formally.
+
+Updating beacons {#updating-beacons}
+------------------------------------
+
+
+ To set the url of a pending beacon |beacon| to a [=/URL=] |url|:
+ 1. If |beacon|'s [=pending beacon/is_pending=] is false, return false.
+ 1. If |url| is not a valid [=/URL=], return false.
+ 1. If |url| is not a [=potentially trustworthy URL=], return false.
+ 1. Set |beacon|'s [=pending beacon/url=] to |url|.
+ 1. Return true.
+
+
+
+
+ To set the method of a pending beacon |beacon| to a string |method|:
+ 1. If |beacon|'s [=pending beacon/is_pending=] is false, return false.
+ 1. If |method| is not a case-insensitive match for "GET" or "POST", return false.
+ 1. Set |beacon|'s [=pending beacon/method=] to |method|.
+ 1. Return true.
+
+
+
+
+ To set the timeout of a pending beacon |beacon| to an integer |timeout|:
+ 1. If |beacon|'s [=pending beacon/is_pending=] is false, return false.
+ 1. If |timeout| is negative, return false.
+ 1. Set |beacon|'s [=pending beacon/timeout=] to |timeout|.
+ 1. Return true.
+
+
+
+
+ To set the payload of a pending beacon |beacon| to a [=byte sequence=] |payload|,
+ 1. If |beacon|'s [=pending beacon/is_pending=] is false, return false.
+ 1. Set |beacon|'s [=pending beacon/payload=] to |payload|.
+ 1. Return true.
+
+
+
+
+ To cancel a [=pending beacon=] |beacon|, set |beacon|'s [=pending beacon/is_pending=] to false.
+
+ Note: Once canceled, a [=pending beacon=]'s payload will no longer be used,
+ and it is safe for a user agent to discard that, and to cancel any associated
+ timers. However, other attributes may still be read, and so this algorithm
+ does not destroy the beacon itself.
+
+
+Sending beacons {#sending-beacons}
+----------------------------------
+
+Note: This is written as though Fetch were used as the underlying mechanism.
+However, since these are sent out-of-band, an implementation might not use the
+actual web-exposed Fetch API, and may instead use the underlying HTTP primitives
+directly.
+
+
+ To send a document's beacons, given a Document |document|, run these steps:
+
+ 1. For each [=pending beacon=] |beacon| in |document|'s [=pending beacon set=],
+ 1. Call [=send a queued pending beacon=] with |beacon|.
+
+
+
+
+ To send a queued pending beacon |beacon|, run these steps:
+
+ 1. If |beacon|'s [=pending beacon/is_pending=] flag is false, then return.
+ 1. Set |beacon|'s [=pending beacon/is_pending=] flag to false.
+ 1. Check permission.
+ 1. If |beacon|'s [=pending beacon/method=] is "GET", then call [=send a pending beacon over GET=] with |beacon|.
+ 1. Else call [=send a pending beacon over POST=] with |beacon|.
+
+Issue: "Check permission" is not defined. A specific permission should be used
+here, and this should integrate with the permissions API.
+
+
+
+ To send a pending beacon over GET, given a pending beacon |beacon|:
+
+ 1. Let |pairs| be the [=/list=] « ("data", |beacon|'s [=pending beacon/payload=]) ».
+ 1. Let |query| be the result of running the [=urlencoded serializer=] with |pairs|.
+ 1. Let |url| be a clone of |beacon|'s [=pending beacon/url=].
+ 1. Set |url|'s query component to |query|.
+ 1. Let |req| be a new [=/request=] initialized as follows:
+
+ : method
+ :: GET
+ : client
+ :: The entry settings object
+ : url
+ :: |url|
+ : credentials mode
+ :: same-origin
+
+ 1. Fetch |req|.
+
+
+
+
+ To send a pending beacon over POST, given a pending beacon |beacon|:
+
+ 1. Let |transmittedData| be the result of serializing |beacon|'s [=pending beacon/payload=].
+ 1. Let |req| be a new [=/request=] initialized as follows:
+
+ : method
+ :: POST
+ : client
+ :: The entry settings object
+ : url
+ :: |beacon|'s [=pending beacon/url=]
+ : header list
+ :: headerList
+ : origin
+ :: The entry settings object's [=/origin=]
+ : keep-alive flag
+ :: true
+ : body
+ :: |transmittedData|
+ : mode
+ :: cors
+ : credentials mode
+ :: same-origin
+
+ 1. Fetch |req|.
+
+Issue: headerList is not defined.
+
+
+
+
+Integration with HTML {#integration}
+====================================
+
+Note: The following sections modify the [[HTML]] standard to enable sending of
+beacons automatically by the user agent. These should be removed from this spec
+as appropriate changes are made to [[HTML]].
+
+When a document with a non-empty [=pending beacon set=] is to be discarded, send the document's pending beacons.
+
+Issue: "discarded" is not well defined.
+
+When a process hosting a document with a non-empty [=pending beacon set=] crashes,
+send the document's pending beacons.
+
+Issue: The concepts of "process" and "crashes" are not well defined.
+
+
+When a [=Document=] |document| is to become hidden (visibility state change), run these steps:
+
+1. For each [=pending beacon=] |beacon| in |document|'s [=pending beacon set=],
+ 1. Let |timeout| be |beacon|'s [=pending beacon/timeout=].
+ 1. If |timeout| is not null, start a timer to run a task in |timeout| ms.
+
+ Note: The user agent may choose to coalesce multiple timers in order to send
+ multiple beacons at the same time.
+
+ 1. When the timer expires, call [=send a queued pending beacon=] with |beacon|.
+
+ Note: The pending beacons may have been sent before this time, in cases
+ where the document is unloaded, or its hosting process crashes before the
+ timer fires. In that case, if the user agent still reaches this step, then
+ the beacons will not be sent again, as their [=pending beacon/is_pending=]
+ flag will be false.
+
+Issue: "visibility state change" should be more specific here, and should refer
+to specific steps in either [[PAGE-VISIBILITY]] or [[HTML]]
+
+
+A {{PendingBeacon}} object has an associated beacon, which is a [=pending beacon=].
+
+
+ The new PendingBeacon(|url|, |options|) steps are:
+
+ 1. Let |beacon| be a new [=pending beacon=].
+ 1. Set [=this=]'s [=PendingBeacon/beacon=] to |beacon|.
+ 1. Set [=this=]'s {{PendingBeacon/url}} to |url|.
+ 1. If |options| has a {{PendingBeaconOptions/method}} member, then set
+ [=this=]'s {{PendingBeacon/method}} to |options|'s
+ {{PendingBeaconOptions/method}}.
+ 1. If |options| has a {{PendingBeaconOptions/pageHideTimeout}} member, then set [=this=]'s
+ {{PendingBeacon/pageHideTimeout}} to |options|'s {{PendingBeaconOptions/pageHideTimeout}}.
+ 1. Insert |beacon| into the user agent's pending beacon set.
+
+
+
+
+ The url getter steps are to return [=this=]'s [=PendingBeacon/beacon=]'s [=pending beacon/url=].
+
+
+
+
+ The {{PendingBeacon/url}} setter steps are:
+ 1. Let |beacon| be [=this=]'s [=PendingBeacon/beacon=].
+ 1. If |beacon|'s [=pending beacon/is_pending=] is not true, throw a {{"NoModificationAllowedError"}} {{DOMException}}.
+ 1. Let |urlString| be the argument to the setter.
+ 1. If |urlString| is not a [=valid URL string=], throw a {{TypeError}}.
+ 1. Let |base| be the entry settings object's [=API base URL=].
+ 1. Let |url| be the result of running the [=URL parser=] on |urlString| and |base|.
+ 1. If |url| is failure, throw a {{TypeError}}.
+ 1. If the result of setting |beacon|'s [=pending beacon/url=] to |url| is false, throw a {{TypeError}}.
+
+
+
+
+ The method getter steps are to return [=this=]'s [=PendingBeacon/beacon=]'s [=pending beacon/method=].
+
+
+
+
+ The {{PendingBeacon/method}} setter steps are:
+ 1. Let |beacon| be [=this=]'s [=PendingBeacon/beacon=].
+ 1. If |beacon|'s [=pending beacon/is_pending=] is not true, throw a {{"NoModificationAllowedError"}} {{DOMException}}.
+ 1. Let |method| be the argument to the setter.
+ 1. If the result of setting |beacon|'s [=pending beacon/method=] to |method| is false, throw a {{TypeError}}.
+
+
+
+
+ The pageHideTimeout getter steps are to return [=this=]'s [=PendingBeacon/beacon=]'s [=pending beacon/timeout=].
+
+
+
+
+ The {{PendingBeacon/pageHideTimeout}} setter steps are:
+ 1. Let |beacon| be [=this=]'s [=PendingBeacon/beacon=].
+ 1. If |beacon|'s [=pending beacon/is_pending=] is not true, throw a {{"NoModificationAllowedError"}} {{DOMException}}.
+ 1. Let |timeout| be the argument to the setter.
+ 1. If |timeout| is not a non-negative integer, throw a {{TypeError}}.
+ 1. If the result of setting |beacon|'s [=pending beacon/timeout=] to |timeout| is false, throw a {{TypeError}}.
+
+
+
+
+ The isPending getter steps are to return [=this=]'s [=PendingBeacon/beacon=]'s [=pending beacon/is_pending=] flag.
+
+
+
+
+ The deactivate() steps are:
+ 1. Let |beacon| be [=this=]'s [=PendingBeacon/beacon=].
+ 1. If |beacon|'s [=pending beacon/is_pending=] is not true, throw an {{"InvalidStateError"}} {{DOMException}}.
+ 1. [=pending beacon/cancel=] |beacon|.
+
+
+
+
+ The setData(|data|) steps are:
+ 1. Let |beacon| be [=this=]'s [=PendingBeacon/beacon=].
+ 1. If |beacon|'s [=pending beacon/is_pending=] is not true, throw a {{"NoModificationAllowedError"}} {{DOMException}}.
+ 1. Let (|body|, contentType) be the result of extracting a [=body with type=] from |data| with keepalive set to true.
+ 1. Let |bytes| be the [=byte sequence=] obtained by reading |body|'s stream.
+ 1. If the result of setting |beacon|'s [=pending beacon/payload=] to |bytes| is false, throw a {{TypeError}}.
+
+
+
+
+ The sendNow() steps are:
+ 1. Let |beacon| be [=this=]'s [=PendingBeacon/beacon=].
+ 1. If |beacon|'s [=pending beacon/is_pending=] is not true, throw an {{"InvalidStateError"}} {{DOMException}}.
+ 1. Call [=send a queued pending beacon=] with |beacon|.
+
+
+
+Privacy {#privacy}
+==================
+
+Issue: This section is woefully incomplete. These all need to be fleshed out in
+enough detail to accurately describe the privacy issues and suggested or
+prescribed mitigations.
+
+* When the network changes, drop all queued beacons
+
+* Clear-site-data?
+
+* Incognito?
diff --git a/index.html b/index.html
new file mode 100644
index 0000000..9600bc8
--- /dev/null
+++ b/index.html
@@ -0,0 +1,1758 @@
+
+
+
+
+ Page Unload Beacon
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
This document introduces an API for registering data to be sent to a predetermined server
+
+ at the point that a page is unloaded.
+
+
Status of this document
+
+
This section describes the status of this document at the time of its publication.
+ A list of current W3C publications
+ and the latest revision of this technical report
+ can be found in the W3C technical reports index at https://www.w3.org/TR/.
+
GitHub Issues are preferred for discussion of this specification.
This document was produced by a group operating under the W3C Patent Policy.
+ W3C maintains a public list of any patent disclosures made in connection with the deliverables of the group;
+ that page also includes instructions for disclosing a patent.
+ An individual who has actual knowledge of a patent which the individual believes
+ contains Essential Claim(s) must disclose the information in accordance with section 6 of the W3C Patent Policy.
+
+
+
+
+
+
1. Introduction
+
This is an introduction.
+
This introduction needs to be more of an introduction.
+
2. Pending Beacon Framework
+
2.1. Concepts
+
A pending beacon represents a piece of data which has been
+registered with the user agent for later sending to an origin server.
Note: In this spec, the pending beacon set is associated with a Document.
+In an actual implementation, this set will likely need to be stored in the user
+agent, separate from the document itself, in order to be able to send beacons
+when the document is destroyed (either by being unloaded, or because of a crash).
+
Define these to be part of the user agent formally.
+
2.2. Updating beacons
+
+ To set the url of a pending beacon beacon to a URLurl:
+
+
Note: Once canceled, a pending beacon's payload will no longer be used,
+ and it is safe for a user agent to discard that, and to cancel any associated
+ timers. However, other attributes may still be read, and so this algorithm
+ does not destroy the beacon itself.
+
+
2.3. Sending beacons
+
Note: This is written as though Fetch were used as the underlying mechanism.
+However, since these are sent out-of-band, an implementation might not use the
+actual web-exposed Fetch API, and may instead use the underlying HTTP primitives
+directly.
+
+ To send a document’s beacons, given a Document document, run these steps:
+
+
Note: The following sections modify the [HTML] standard to enable sending of
+beacons automatically by the user agent. These should be removed from this spec
+as appropriate changes are made to [HTML].
Note: The pending beacons may have been sent before this time, in cases
+where the document is unloaded, or its hosting process crashes before the
+timer fires. In that case, if the user agent still reaches this step, then
+the beacons will not be sent again, as their is_pending flag will be false.
+
+
"visibility state change" should be more specific here, and should refer
+to specific steps in either [PAGE-VISIBILITY] or [HTML]
This section is woefully incomplete. These all need to be fleshed out in
+enough detail to accurately describe the privacy issues and suggested or
+prescribed mitigations.
+
+
+
When the network changes, drop all queued beacons
+
+
Clear-site-data?
+
+
Incognito?
+
+
+
+
Conformance
+
Document conventions
+
Conformance requirements are expressed
+ with a combination of descriptive assertions
+ and RFC 2119 terminology.
+ The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL”
+ in the normative parts of this document
+ are to be interpreted as described in RFC 2119.
+ However, for readability,
+ these words do not appear in all uppercase letters in this specification.
+
All of the text of this specification is normative
+ except sections explicitly marked as non-normative, examples, and notes. [RFC2119]
+
Examples in this specification are introduced with the words “for example”
+ or are set apart from the normative text
+ with class="example",
+ like this:
+
+
+
This is an example of an informative example.
+
+
Informative notes begin with the word “Note”
+ and are set apart from the normative text
+ with class="note",
+ like this:
+
Note, this is an informative note.
+
Conformant Algorithms
+
Requirements phrased in the imperative as part of algorithms
+ (such as "strip any leading space characters"
+ or "return false and abort these steps")
+ are to be interpreted with the meaning of the key word
+ ("must", "should", "may", etc)
+ used in introducing the algorithm.
+
Conformance requirements phrased as algorithms or specific steps
+ can be implemented in any manner,
+ so long as the end result is equivalent.
+ In particular, the algorithms defined in this specification
+ are intended to be easy to understand
+ and are not intended to be performant.
+ Implementers are encouraged to optimize.
The concepts of "process" and "crashes" are not well defined. ↵
+
"visibility state change" should be more specific here, and should refer
+to specific steps in either [PAGE-VISIBILITY] or [HTML]↵
+
This section is woefully incomplete. These all need to be fleshed out in
+enough detail to accurately describe the privacy issues and suggested or
+prescribed mitigations. ↵
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file