beeminder push to beeminder, aka rudimentary meta integration, aka disintermediate IFTTT for foo-days goals

I’m heavily plagiarizing Danny’s beemail about the same, but I thought maybe there are people more likely to use the forum than read a beemail? Plus having this written down somewhere in public is probably good?

We have a baby step towards our meta integration that we’re ready for some beta testers for.

Let’s say you have a weight goal and a weighins goal and you want the weighins goal to automatically get a +1 when you add a datapoint to your weight goal. (We definitely recommend this for beeminding weight, btw.)

Previously you could do that with IFTTT but now you can do it with just Beeminder. :confetti_ball:! Just that it’s a little obscure for now, while we figure out the best way to expose this to the hoi polloi.

To spell out the way to use this, assume your username is bob and you have these two goals:

Main goal:
Meta goal:

Just go to the Settings tab for your main goal, scroll down to the DATA section, look for the Webhook field, and paste in the URL of your meta goal. That’s it. Now your meta goal will get an automatic +1 when you add data to your main goal.

Technical details

What I did was add a Beeminder API endpoint that is a webhook receiver, so that rather than having to host your own server to receive pushes from that webhook callback, you could just point Beeminder at itself… so when you put in that field, we’re actually transforming that into the following Beeminder API URL:

We could technically have done this without the new API endpoint, by just changing the validation to allow a Beeminder API URL in that webhook field and then you’d use the API’s datapoints resource as the webhook URL, which is a bit more direct, without adding new API endpoints. But this way we can add features to that webhook receiver in the future, things that would be more like our IFTTT macros, or let you do more things with that pushed data. Anyway.

We also implemented a loop detection step (thanks to @theospears and @poisson and @rperce in the community Discord for helping with that) to the validation on the webhook URL field, so you can’t create obvious infinite loops, having two Beeminder goals (or a cycle of them) pushing data to each other in an infinite loop.


One potential thing with this is that if you have an autodata goal pushing to a meta goal and the autodata goal has plenty of safety buffer but it’s a beemergency on the meta goal, Beeminder is unaware of the urgency on the autodata goal and may not fetch data fast enough. (Normally Beeminder is careful to do a final fetch of autodata before derailing you.) As long as you’re aware of this you can just hit the fetch button on the autodata (main) goal to make sure it’s fresh in time.

(Which probably makes it sound more complicated than it is. It’s really the same principle of “this goal is red, what does it need / where does its data come from? I better make sure that data is the latest data!” And to be clear, there’s no delay between the main goal getting data and the meta goal getting its +1 so this is only an issue for an autodata goal that may be waiting on data from the autodata source and a meta goal waiting on that autodata goal. We’re working on making the main goal aware of the meta beemergency and do more frequent auto-fetches so you can safely think about this potential gotcha even less than this.)


What about three goals that send data to each other?

Goal A → Goal B → Goal C → Goal A

What would happen?
Am I allowed to try this?

Also, congrats on your new feature


We detect the cycle and don’t allow it! Thanks for asking before risking taking down the whole website! :sweat_smile:


Nifty! I’m using this with my aerobic goal, which records time spent on cardio exercises. It sends data to my new aerobic_meta goal, which has a rate of 6/7. This means that I’m encouraged to do some cardio 6 days a week even if I have a safety buffer on my original timed goal.

I have the aerobic_meta goal set to the binary aggregation method so that if I do two cardio sessions in one day, I do not accumulate extra buffer on the meta goal.

The aerobic goal takes manual datapoints for the time spent exercising, rather than using Toggl. This wouldn’t work with a Toggl integration goal since they get a datapoint of 0 on any day where no time was recorded, which I assume would still cause a meta goal to have a datapoint of 1.


Try nonzero aggday, alys, it may do what you’re looking for!


That doesn’t seem to help, but thank you for the suggestion. Here’s what I tried:

  1. Pick a Toggl integration goal (breathing) and add my meta goal to its webhook field (I’ll delete that webhook in a day or two).
  2. Set the breathing goal to custom with nonzero for the Aggregation (previously it was sum, and I’ll change it back to that in a day or two).
  3. Delete the current breathing datapoint for the day (which was for 0 hours).
  4. Click the breathing goal’s button to fetch data from Toggl, causing a new 0 datapoint to be entered on the breathing goal.
  5. Observe that a +1 datapoint was still added to the meta goal.

Setting the meta goal to nonezero also didn’t help (still a +1 datapoint was added). I’ve changed the meta goal back to binary.

1 Like

@bee That test let me find a small bug though! :slight_smile:

After following steps 1 to 5 in my previous comment, the datapoint added to my meta goal in step 5 had this as the comment:
new datapoint added to alys/breathing
(i.e., there’s a double space after “datapoint” instead of a date and a value).

I was expecting to see either of these comments (I wouldn’t care which one):
new datapoint 31 0:00 added to alys/breathing
new datapoint 31 0 added to alys/breathing

1 Like

Because we’re talking about the meta goal, it only gets +1 datapoints, regardless of the original value.

Unless we’ve special-cased them, the non-datapoint datapoints like derailment and goal restarts will also push a +1 to the meta goal.

I think a good and non-confusing upgrade to the meta integration would be to default to sending +1 for non-zero datapoints and 0 for zero datapoints.

In that case, useful aggregation methods on the meta goal would include:

  • ‘binary’ (sic) for counting days that have had any activity
  • ‘nonzero’ for counting days that have had any datapoints that weren’t zero
  • ‘count’ for counting the number of times you did the activity, i.e. it can be done more than once per day
  • ‘sum’ for counting the number of times you did non-zero activity

We could make those options available on the meta-goal creation page.

For the canonical use case of ‘did I weigh in today?’ the correct default is obviously ‘nonzero’, which implies by symmetry that the default for counting ‘times’ rather than ‘days’ should be ‘sum’.

Which in turn simplifies the UX — leave the folks who want to count the zeros to adjust the aggregation settings themselves, and ask whether this is something that tracks the number of days on which X occurred, or the number of times X was entered.


This is great stuff! I’ve created a new thread over here where people might add their use cases for metaminding, as I’m really excited about its potential. (I’m mentally reserving this thread for the more technical stuff!)


ooh! interesting. I used the datapoint field urtext for the comment, forgetting/failing to grok that urtext is not set by all forms of adding datapoints… which leads me back to a gissue pointing out that the webhook callback url data format is inconsistent compared to the api datapoints endpoint.

Anyway, I’ll update things a little so that doesn’t happen.

For the non-zero aggday to work in this scenario, you’d want to mirror the actual datapoint value to the meta goal, which is definitely on the list of things to add to the meta integration. But also I think it constitutes a bug that the Toggl integration adds zero datapoints, since the metric we typically use for goal “activeness” is “when were datapoints last added”, so it’s better if an autodata goal like toggl only adds non-zero data, so I’m adding a gissue for that too (though I really thought we had it gissued somewhere already but I can’t find it now, so…).


I suggest bolding this portion of the post. In glancing at this post, I got the impression that this would be hard and was going to not bother doing it. Later, I convinced myself to give it a try and actually read the post and then realized how easy it was.