What is This?
- This is an API that allows you to send any emoji (aka reaction 💥) about a website.
- You can get all reactions for a website, or just a specific one.
- To use, you create a client key and place that in your website.
That’s about it
The entire API is defined in the OpenApi link above.
You may use the API to manage your keys, or use the web app to manage your keys.
How do I use it?
Let’s assume you’ve subscribed ✨ received your master key (m_1234
) and you want to let users react to your page (example.com/mysite).
Create the Client Key
First, let’s create a client key (or just use the app). We’ll limit it to this page and allow.. 100 reactions a month.
async function createKey(maxCount: number, hostname: string): string {
const res = fetch("https://heart.sandcatdev.com/v1/keys", {
method: "POST",
headers: {
Authorization: "Bearer m_1234",
Accept: "application/json",
},
body: JSON.stringify({
hostname: "example.com/mysite",
max_count: 100,
})
})
if (res.ok) {
const resJson = await res.json()
return resJson.data.key.token
}
}
console.log(await createKey(100, "example.com/mysite"))
// c_b00dd3285e621a487af98e08099cdce8
Form Embed
Next, we’ll embed this into our form:
<meta charset="UTF-8">
<form action="https://heart.sandcatdev.com/v1/reactions/example.com/mysite?token=c_b00dd3285e621a487af98e08099cdce8&redirect=https://example.com"
method="POST"
enctype="application/x-www-form-urlencoded"
>
<button type="submit" name="💖">💖</button>
</form>
All done! You have two options when it comes to forms:
- Redirect to the
Referer
provided (this is the default). If you send the reaction from https://example.com/mysite, it will redirect to https://example.com/mysite after completing. - Manually set the redirect.
<form action="https://heart.sandcatdev.com/v1/reactions/example.com/mysite?
token=c_b00dd3285e621a487af98e08099cdce8
&redirect=https://example.com/anothersite"
After the redirect, the next page load will handle the updated reaction count.
This requires no javascript. However, for a live updating version, we can use the next example.
Javascript
Updating Button
First, let’s define two crucial functions:
- Getting the reaction count
- Sending a new reaction
async function getReactionCount(elementId, url, emoji) {
try {
const response = await fetch(`https://heart.sandcatdev.com/v1/reaction/${emoji}/${url}`);
if (response.ok) {
const count = await response.text();
document.getElementById(elementId).textContent = count;
}
} catch (error) {
console.error('Error fetching reaction:', error);
}
}
async function sendReaction(token, elementId, url, emoji) {
try {
const response = await fetch(`https://heart.sandcatdev.com/v1/reactions/${emoji}/${url}`, {
method: 'POST',
headers: {
'Content-Type': 'text/plain',
Accept: 'text/plain',
Authorization: `Bearer ${token}`
},
body: emoji,
});
if (response.ok) {
const count = await response.text();
document.getElementById(elementId).textContent = count;
}
} catch (error) {
console.error('Error sending reaction', error);
}
}
Now let’s write the html and put in an event listener to trigger when we click the button.
The element we’ll update will be mysite-dom-id
<meta charset="UTF-8">
<div>
<span id="reaction-container">My Site has <span id="mysite-dom-id">0</span>💖</span>
</div>
<script>
document.addEventListener('DOMContentLoaded', () => {
updateReactionCount("mysite-dom-id", "example.com/mysite", "💖");
document.getElementById("reaction-container").addEventListener('click', () => {
sendReaction("c_862037d693b9472eb9b30b7ce4334cae", "mysite-dom-id", "example.com/mysite", "💖");
});
});
</script>
React Component
We also provide a React component you may use, rather than implementing the logic from scratch.
import { HeartButton } from 'react-heart-button';
function App() {
return (
<HeartButton
url="example.com/mysite"
emoji="❤️"
token="c_b00dd3285e621a487af98e08099cdce8"
/>
);
}
Hugo
Create a file called layouts/partials/reactions.html
and include the following:
<script>
async function getReactionCount(elementId, url, emoji) {
try {
const response = await fetch(`https://heart.sandcatdev.com/v1/reaction/${emoji}/${url}`);
if (response.ok) {
const count = await response.text();
document.getElementById(elementId).textContent = count;
}
} catch (error) {
console.error('Error fetching reaction:', error);
}
}
async function sendReaction(token, elementId, url, emoji) {
try {
const response = await fetch(`https://heart.sandcatdev.com/v1/reactions/${emoji}/${url}`, {
method: 'POST',
headers: {
'Content-Type': 'text/plain',
Accept: 'text/plain',
Authorization: `Bearer ${token}`
},
body: emoji,
});
if (response.ok) {
const count = await response.text();
document.getElementById(elementId).textContent = count;
}
} catch (error) {
console.error('Error sending reaction', error);
}
}
</script>
Now create the shortcode at layouts/shortcodes/react.html
:
{{/*
Hugo shortcode for sending reactions.
Usage:
{{< react url="/my-page" emoji="❤️" token="c_123" >}}
*/}}
{{- $url := .Get "url" -}}
{{- $emoji := .Get "emoji" -}}
{{- $token := .Get "token" -}}
{{- $domId := printf "reaction-count-%s-%s" $url $emoji -}}
{{- $apiServer := "https://heart.sandcatdev.com" -}}
{{- if and $url $emoji -}}
<button onclick="sendReaction('{{ $token }}', '{{ $domId }}', '{{ $url }}', '{{ $emoji }}')">
{{ $emoji }} <span id="reaction-count-{{ $url }}-{{ $emoji }}"></span>
</button>
<script>
getReactionCount('{{ $domId }}', '{{ $url }}', '{{ $emoji }}');
</script>
{{- else -}}
<p style="color: red;">Error: Both `url` and `emoji` parameters are required for the `react` shortcode.</p>
{{- end -}}
Make sure to load the reactions.html somewhere in the head.
{{ partialCached "reactions.html" . }}
And now we’re ready to use it!
{{< react url="example.com/mysite" emoji="💡" token="c_b00dd3285e621a487af98e08099cdce8" >}}
FAQ
- Is it safe to put client keys in the code?
Yes! When creating (or updating) the key, you may specify how many reactions can be sent per month, as well as which hostnames users may send a reaction to.
Irregardless, please feel free to regenerate your token. through the PUT http method or the app (click on the eye and click on Regenerate Token). - How secure is the reaction count?
Anyone may send any reaction to any url. This means reaction counts can be boosted significantly. Consider this a fun minimal service, rather than using this to determine any metrics. - I lost my master token. What do I do now?
Go to the app and click on Lost Token?. - The emoji is corrupted!
Make sure to place this meta tag in there.
Otherwise, you might get strange encodings with emoji’s like 💖 turning into something like ðŸ'–
<meta charset="UTF-8">