Tracking Habitica Habits

Hi everyone,

I was excited to integrate Beeminder with Habitica, but because of the limitations of the way the current integration works, I need your help finding a workaround (with IFTTT) :slight_smile:

As you might know, Habitica differentiates between

  1. Habits (eg. a 30min workout that you can check off any time. Can be positive or negative habits, depending on whether you click + or -)
  2. Dailies (reduces health automatically if not completed)
  3. To Dos (just a To Do list)

Beeminder only reads To Dos. Someone can set a minimum of To Dos, that need to be completed in a selected timeframe. This might be cool, if you manage your To Dos in Habitica.
I and many people do not even use the To Do section. I only use 1) Habits and 2) Dailies. To keep myself accountable to habits, whether they have to be completed daily or not.

That being said, I would be happy, if you help me find a solution, so that I can add goals in Beeminder, that track 1) habits. (e.g. workout habit performed at least 3x / week)
I know that the Habitica API can read, when a habit has been clicked (+/-), because a tool, called “Habitica Data Display Tool” can read that out, along with lots of other user data.
I just don’t know how and I would like to feed that information into Beeminder, using IFTTT. I have some programming skills, but if you have an idea of how I could go about this, it would be much appreciated.

1 Like

What? Beeminder only supports the ToDos of Habitica?? That sounds very pointless.

I bet @shanaqui can help :slight_smile:

Your faith in me is touching, but I cannot actually help! I suggested posting here in the first place, in case anyone has any ideas and so I could call in @alys . As I recall, there are technical limitations why we don’t pick up Habits, but I’m not sure. (We don’t just pick up To-Dos, though – we do pick up Dailies as well. Not sure where that confusion came in! The limitation for Dailies is that we need your custom day start on Habitica to be set to the default midnight; if it isn’t, you can’t even set up a goal, IIRC.)

2 Likes

Pretty much the biggest problem with supporting Habits was a lack of time to write the code. :frowning: I was working on the Beeminder-Habitica integration but I was also massively over-committed on other things and still haven’t really recovered from the burnout.

There are some technical limitations that would make Habits harder to track in Beeminder than Dailies and To-Dos. I wrote something about it at Habitica: How it Works; How Beeminder's Integration Works and meant to write more but… yeah… time.

Habitica does have webhooks, including for when a task is “scored” (completed or plussed/minused), so setting up a webhook in Habitica that populates a Beeminder goal via a script or via IFTTT might be one option to work around the current lack of an official integration.

2 Likes

In the “Data Display Tool” you can see the habit history. With dates, but without exact timestamps. Though you probably know that.

As for webhooks, I’ve checked out the API docs, but I have to admit, I’m pretty clueless.

When I look at the IFTTT webhook service, this is the info I get:

And in the Habitica settings I can enter webhook URLs. Where I would assume, I’d put in the URL from the image.
But how does the webhook code from here and the parameters from the Habitica API docs come into play?
Surely I have to specify “type” (I’m assuming “taskActivity”) somewhere. And specify the contents of the .json object, that is postet. And somehow tell it what habit should trigger it.

I might be in over my head with this :confused:

Alys definitely knows that. She made the data display tool. :wink: :laughing:

2 Likes

Habitica used to record the timestamps for each Habit click, with one entry in the Habit’s history for each click, but that caused significant performance issues for anyone with a lot of history. Now there’s just one entry per day with a count of how many times the plus and minus buttons were clicked that day (the scoredUp and scoredDown values shown in the data dump in Habitica: How it Works; How Beeminder's Integration Works).

Webhooks are a part of Habitica’s API but if you use a webhook you don’t need to know anything else about the API. The webhook’s setting in your Habitica account points to a URL in a different service and that service doesn’t need to use Habitica’s API. When you take an action in Habitica (e.g., clicking plus on a Habit), the webhook for that action is triggered and data about the action is sent to the URL that you’ve specified. The URL needs to point to a script (or something similar) that is able to handle that data, so the thing you’d need to do is work out how to write such a script or (more likely in your case) how to configure IFTTT to process the data correctly.

I’ve never actually used Habitica’s webhooks but I’ll have a poke around in our docs and things to see if I can find useful examples for you. I’ll post again here, even if I don’t find anything. http://alys.commits.to/look_into_webhooks_for_habits_and_post_to_tracking-habitica-habits_5715

5 Likes

It’s relatively easy to use IFTTT with Habitica’s webhook feature to update a Beeminder goal to record ALL of your clicks on ALL Habitica task types. That includes clicks on the negative button of Habits and purchases of Rewards (which are stored internally in Habitica as a type of task). I’ve written up the process for that in Habitica’s Beeminder wiki page in the “Tracking All Task Types using IFTTT” section, since that wiki is the best place for any long-term documentation for anything related to Habitica. If you have questions about anything I’ve written there, ask here and I’ll answer and/or clarify the instructions. If anyone can see a way to improve those instructions either edit that wiki page (you don’t need a Wikia / Fandom account) or comment here and I’ll update it.

If you use Habitica for only positive Habits and/or Dailies and/or To-Dos and want to record all of them, then that process would work for you.

If you also use negative Habits or Rewards, it would not work because those would always be included as datapoints in your Beeminder goal (using the same value for the datapoints as for positive Habits and the other task types). It’s not possible to adjust that process to prevent negative Habits and Rewards from being recorded.

It would be possible to write a custom script that you could use in Habitica’s webhooks feature to update a Beeminder goal with a customised selection of task types (e.g., to exclude negative Habits and Rewards) but that would be more complex, especially if you’re not familiar with programming. It would not involve Habitica’s API; you would just enter the URL to your script into Habitica’s webhook form. Whenever you completed a task in Habitica (including buying Rewards), the webhook would send data to your script. The data would indicate which task had been used (the text value), what the task type was (habit, daily, todo, or reward), and what the direction was (up for positive Habits or completed Dailies or completed To-Dos or purchased Rewards; down for negative Habits or Dailies/To-Dos that you’d marked as incomplete by unticking them). Your script would parse that data and if the combination of values indicated it was a task you wanted to track, your script would update your Beeminder goal. Below is a sub-set of the data that your script would receive from Habitica.

{
	"direction":"up",
	"task": {
		"type":"habit",
		"tags":[ ... tag IDs here ... ],
		"priority":1.5,
		"attribute":"str",
		"_id":"the-task's-id",
		"text":"title of task here",
		"webhookType":"taskActivity",
		... and a lot of other data ...
	}
	... and other data ...
}
3 Likes

Well I do have some programming experience(nothing with webhooks though), so I’m not gonna give up that easily, but I’ll need a few more clues to get going.

So my goal is to set up Beeminder goals, that each track a specific habit(be it positive or negative).

What tools could I use to implement this? Where could I hose the script, that checks if the json object has text = specific_habit in it?
Would I have to implement a webhook, that listens to a specific URL(that I’ll tell Habitica about), inside that script? Assuming yes: if using this code, where would I state the URL?
How would I connect that script with IFTTT? Would I even use the webhook service in IFTTT?

Thanks for you help! I hope I’m not overwhelming you with my newbie questions.

PS: I’ve improved the Habitica Wiki file and documented the changes

1 Like

With some programming experience, getting what you want is possible!

I suggest not using IFTTT at all because it in my opinion it adds unnecessary complexity (if others here express different opinions, do consider them though). Your script would read directly from Habitica’s data and would write directly to Beeminder goals.

The script could be written in any language. What ones are you most comfortable with?

It would need to be hosted on a website somewhere. If you own a site yourself, that’s easy. Otherwise there’s probably options for hosting it somewhere for little or no money and I’m hoping someone will chime in about this. :slight_smile:
It might be possible to use Google Apps Script for this, which would solve the hosting problem if you have a Google account. Apps Script has support for using APIs (i.e., to use Beeminder’s API to write to the goals). Some really quick-and-dirty googling indicates that you can probably use an Apps Script as an endpoint for Habitica’s webhook (example).

Coding for webhooks isn’t significantly different than any other kind of coding. Webhooks are really just a way of getting data into a script. You’d write a script that would:

  1. read incoming JSON data that identifies a task and how that task had just been used
  2. work out if the task was one you were interested in
  3. work out which Beeminder goal to update
  4. use Beeminder’s API to send a datapoint to that goal

Once you had that script hosted somewhere, you’d put that URL into Habitica’s webhooks form (in the Settings area of Habitica’s website), and then whenever you used a task, Habitica would send data to your script.

If that doesn’t explain the webhooks aspect well enough, say so!
Let us know what you think about all this and what you need to know next.

Thanks heaps for improving the wiki page, especially fixing my “Beeminder” typo! :slight_smile:

2 Likes

Thanks alys,

I have a bit of experience with python, java and js.
Assuming I would use python for this, do you have some suggestions? would you use Flask?

Right now I have a big project to focus on, so I’ll start working on it in 10 days, but I’m looking forward to it.

1 Like

I’ve been using Google Cloud Functions for TaskRatchet, it’s pretty slick and works with Python. Google optionally provisions a URL endpoint that will run your function every time it’s hit, so I imagine you could just give that URL to Habitica and you’d be pretty well set. Your function receives a Flask request object, so no need to configure Flask yourself.

If you decide to go with Python on this, here are a couple Beeminder API wrappers written in Python:

  • beeminderpy - No explicit license, but probably ok in your case.
  • pyminder - MIT licensed, I’m the author. Not well-documented, but I’m happy to help you out if you decide to use it. Also, I’m very open to pull requests.
1 Like

Thanks narthur.
I’m not sure how to test the code in Google Cloud Functions. I can enter a Json object manually and see what the outcome would be. But I have no idea, how I would test it with actual Habitica data.
I also have no idea how I would use your API.

1 Like

If you’re talking about unit testing, you’d probably use Python’s built-in unittest module.

Manual testing: My understanding is that Beeminder would hit the endpoint, and then your code would ping Habitica to get the data, yes? So am I missing something to think that you could just put your endpoint’s URL in the browser, which would trigger your code to talk to Habitica, and then return a response? You could then examine the response right in your browser.

But maybe I’m missing your question.

Yeah, pyminder isn’t very well documented yet. I just added some basic usage notes which should get you on the right track.

If you just want to work with raw API responses, instead of using Pyminder’s data objects, you can use the beeminder API wrapper class directly.