Basically, ditto what Scott said.
Running into the same need myself.
There are two ways to distribute:
- I copy the doc myself and share it with the user but they can’t copy it. I stay the owner.
- I let the user copy the doc and become the owner, shutting me off.
Option 1 means you still have access to the doc — not what users might want. You may sorta sweeten this by creating some dedicated “service” Coda user that you pinky swear not to use — e.g. I have a
Option 2 comes with the issues you outlined: once the doc is not yours, you cannot limit anything about it. The one and only way to make sure it’s not abused is to make it dependent on a pack that you control.
If that pack is for your own backend (e.g. I have a Doc as API pack in the works that uses my own backend as a proxy) then it’s easy — issue access tokens to your backend, make people install the pack with those tokens — anyone without the token will have a bricked doc that won’t work.
If the pack is for Coda API, you can try querying the doc info and checking whether the doc is created from your origin doc, or some other doc (
GET /docs/docID and check the
sourceDoc.id ). If it’s yours then let all the methods work; if it’s not then throw errors.
If the pack is for something you don’t control at all — three options, depending on how many customers you expect:
You can make the pack private and only share it with customers who purchased the template. This way if someone gets an illegal copy of the doc, they won’t be able to access that pack. This only works as long as you can manually share the pack with people, and this can’t be automated yet. Additionally, when you share a pack like this, you give these people the right to install it on any workspace they’re in — so they can, in fact, redistribute illegal doc copies as long as they stay owners of those further copies.
You can collect (if you by any chance can obtain) Doc IDs of the docs that your clients copied for themselves, and hardcode them in the pack’s code. Then on each invocation, check
context.invocationLocation.docId for which doc this pack action or sync was triggered from, and compare to the whitelist of docs. That said,
context.invocationLocation.docId is a deprecated property and one day it will be gone.
Or you can just make it paid. This won’t stop people from copying the doc, but those who get the copies will have to pay a subscription for the pack.
If your doc doesn’t require a pack, then you can deliberately make it require one Just move some of the most critical calculations to the pack instead of formulas, and use one of the methods above. Some people will be able to rebuild it but not many — and those who could would either a) appreciate your effort and pay for it, or b) just build that doc themselves in the first place.
Scott’s solution works as the last resort because if it’s not an essential pack (i.e. just a purchase validation checker) the user will just go and remove it everywhere before reselling the doc, plus it probably slows down the formulas it’s used in.
There are also further shadowy ways, e.g. including some analytics pixel somewhere in the doc that will report back the doc ID it’s used in. It’s against the Terms of Service though.
Finally, you can just trust people.