This is the final report, and all objectives have been achieved, though it would be good to improve optimization in the future. A big usability improvement over the previous version is currency conversion (which wasn't something originally considered), which allows costs and stats to be handled in USD (or other currency of your choice) rather than XRP. Badges on titles help to quickly see if and how a video is monetized. And stats tracking provides more insight on how videos are viewed
An icon by the title of a video showing the user they will skip sponsors can entice the user to choose one video over another. There are three types of video represented (beyond those without monetization). Videos that are simply monetized display a simple Web Monetization logo, those that have sponsor spots that may be skipped have the logo surrounded by a circle. Those that require payment additionally display the cost by the icon. If the user has already paid toward the video that amount is also displayed. The user can simply ignore the badges as well, to no harm.
It's important that users don't have to double-pay for a video (if/when users can pay directly rather than the current unlimited subscription model), so the site must remember what parts of videos have been paid for. As a user views a video, the client remembers which segments are viewed, and the payments with receipts associated with it. Every few seconds it submits this information to the server which verifies the receipts, commits the changes, and sends the new state back to the client.
Similar infrastructure is used to track general viewing stats. The server stores, for each video, the overall amount paid during 15 second segments. It will also record the amount received on each day, and whether the payment came from a subscriber of the channel. Users can also record how much they have contributed to different creators. This tracking can be opted-out by the user in the stats viewing tray.
Stats are viewed by clicking the Web Monetization icon in the video action bar. This displays the total amount paid by the user, the histogram with the amount paid for segments of the video, the per-day revenue, and pie chart of the logged in users contributions by creator. The currency can be changed by a drop-down menu using exchange rates from CoinGecko. The histogram displays all-user stats, and data from the current page view.
These stats provide less-easily-forge-able data about which parts of a video (paying) users are watching, during what days, and whether they are subscribed. It may be useful to compare this data with that from users not contributing by Web Monetization.
This was a detail not originally considered, but nonetheless important. Payments from Coil are made in XRP, but can theoretically be in any sort of asset. Thus, payments are stored as a list of assets and amounts upon receipts. Once submitted to the server for stats, etc., they are converted to the currency specified for the video. This is because it is assumed the author converts the payment upon receipt, and remembering the amount of a more volatile currency such as XRP is not as meaningful.
Users can choose to display values in any currency: USD, XRP, BTC, among others. Directly above, the value is converted to Euros rather than USD. Minimum view costs still display in the currency specified for the video, but conversion to the user's desired currency is shown in parenthesis (e.g. in image of title badges above, BTC is used for the third video).
The main concern is optimization. Receipts are sent fairly often as they come quickly, and they are bundled with their related stats data. PeerTube plugins have fairly rudimentary data storage access at the moment, so it would be good to first store the data in Redis and actually write less often.
It may be possible to improve the view cost setting as Web Monetization evolves. Currently, the uploader can set a minimum cost to view a video, however users cannot change how much Coil pays. This feature is still useful as-is to simply require the same amount that Coil pays, but if some sort of negotiation feature is added to the protocol, it will need to be implemented in this plugin.
Use the plugin and give me your thoughts! I'm open to any suggestions.