@mytiki/tiki-receipt-capacitor v0.3.0
TIKI Receipt (Capacitor + Vue.js)
The TIKI Receipt library adds to your Vue.js + Capacitor mobile app a Data Reward program for your users to share their receipts in-exchange for loyalty points.
Reward users with points for scanning physical receipts, linking their inbox, or connecting one of 58 supported retailer accounts. All program participation data is zero-party, powered by TIKI's data licensing technology, meaning it is data legally owned by an end-user and licensed to yours and other businesses in-exchange for fair-compensation (redeemable loyalty points). Raw receipt data is pooled in a hosted, siloed HUDI data lake, that you can search, query, and train models against. Opt-in to leverage TIKI's data-buyer network to create compensation and cashback rewards for you and your users.
Includes
- Single Vue Component (TikiReceipt) to launch a configurable pre-built UI.
- TypeScript Service Class (TikiService) to interact directly with headless functionality or to build a custom UI.
- TIKI's data licensing SDK (tiki-sdk-capacitor) to create and utilize immutable zero-party data license records.
- Receipt parsing (OCR and scraping) powered by our partners at Microblink.
Microblink is a closed-source, licensed SDK. For new customers, we offer a free Microblink license. Schedule a meeting at mytiki.com to get your license keys.
Installation
npm i @mytiki/tiki-receipt-capacitor @mytiki/tiki-sdk-capacitor @mytiki/tiki-capture-receipt-capacitor
npx cap sync
Next, if you don't already have a publishingId
from TIKI, create a free account and make a project at console.mytiki.com.
Android
Microblink is closed source, and subsequently it's AARs are hosted by Microblink's Maven repository, not Maven Central. You need to add the maven endpoint to your android/build.gradle
file in your project's android folder.
maven { url "https://maven.microblink.com" }
Depending on your project's configuration you may also need to add the following packagingOptions
to your android/app/build.gradle
file.
android {
//... your other android build configs
packagingOptions {
exclude("META-INF/LICENSE-notice.md")
exclude("META-INF/LICENSE.md")
exclude("META-INF/NOTICE.md")
}
}
Getting Started
- Register the plugin with your Vue app
import { createApp } from "vue";
import App from "@/app.vue";
import Tiki from "@mytiki/tiki-receipt-capacitor";
createApp(App)
.use(Tiki, {})
.mount("#app");
This registers the Vue Component as TikiReceipt
and provides Typescript service TikiService
as an injectable object name Tiki
.
- If you're going to use the pre-built UI, add the stylesheet to your main stylesheet (e.g.
main.css
)
@import "@mytiki/tiki-receipt-capacitor/dist/tiki-receipt-capacitor.css";
Configuration
You use the options property of the plugin registration to configure the library for your specific use case.
Config interface reference β
createApp(App)
.use(Tiki, {
//.. your app's configuration
})
Field | Description |
---|---|
key | License keys required for use of the library |
key.publishingId | The publishing ID for your application |
key.scanKey | Your application's BlinkReceipt License Key |
key.intelKey | Your applications' Product Intelligence Key |
program | The description and legal terms of the user's participation in the Data Reward Program. |
program.image | The image src (300x86) to help explain the program and grab the user's attention. |
program.description | A short description explaining the program. |
program.terms | The legal terms and conditions of the program in Markdown format. You can use the example/src/assets/terms.md as a vetted template. |
program.learn | The learn page content in Markdown format. Shown when a user clicks the ? button. You can use the example/src/assets/learn-mored.md as a template/starting point. |
program.bullets | An array (maximum 3) of bullet points explaining how a user's data will be used (true) or not used (false). |
program.bullet.text | The individual bullet's text to display |
program.bullet.isUsed | True if this bullet describes how the user's data will be used, False if it's a use case explicitly disallowed |
program.usecases | An array of all approved data Usecases. These should all fall under one or more of the more user friendly bullets. |
program.destinations | An optional array of approved data processors (e.g. 'mytiki.com') |
program.tags | An optional array of metadata Tags describing the data assets that make up the program. |
reward | An array of Reward offers available to Program participants. |
reward.image | The image src (300x86) to help explain the offer and grab the user's attention. |
reward.description | A short description explaining the reward offer. |
reward.issuer | The issuer function to calculate if a user's action fulfills the offer criteria. Called once per every ReceiptEvent. |
theme | UI style settings and overrides. |
theme.fontFamily | The font family to use. Defaults to "Space Grotesk", sans-serif |
theme.primaryTextColor | The primary text color to use. Defaults to rgb(28 0 0) . |
theme.secondaryTextColor | The secondary text color to use. Defaults to rgb(28 0 0 / 60%) . |
theme.accentColor | The accent color to use. Defaults to rgb(0 178 114) . |
theme.primaryBackgroundColor | The primary background color to use. Defaults to rgb(255 255 255) . |
theme.secondaryBackgroundColor | The secondary background color to use. Defaults to rgb(246 246 246) . |
theme.redeem | A function to execute when a user presses the Redeem Points button. |
Example (example/src/main.ts
)
import "./assets/main.css";
import { createApp } from "vue";
import App from "@/app.vue";
import Program from "@/assets/program.png";
import LinkReward from "@/assets/link-reward.png";
import ScanReward from "@/assets/scan-reward.png";
import MoreReward from "@/assets/more-reward.png";
import LearnMore from "@/assets/learn-more.md?raw";
import Terms from "@/assets/terms.md?raw";
import Tiki, {
CommonTags,
CommonUsecases,
Tag,
Usecase,
ReceiptEvent,
} from "@mytiki/tiki-receipt-capacitor";
import type { Receipt, ReceiptAccount } from "@mytiki/tiki-receipt-capacitor";
createApp(App)
.use(Tiki, {
key: {
publishingId: "be19730a-00d5-45f5-b18e-2e19eb25f311",
scanKey:
"sRwAAAAoY29tLm15dGlraS5zZGsuY2FwdHVyZS5yZWNlaXB0LmNhcGFjaXRvcgY6SQlVDCCrMOCc/jLI1A3BmOhqNvtZLzShMcb3/OLQLiqgWjuHuFiqGfg4fnAiPtRcc5uRJ6bCBRkg8EsKabMQkEsMOuVjvEOejVD497WkMgobMbk/X+bdfhPPGdcAHWn5Vnz86SmGdHX5xs6RgYe5jmJCSLiPmB7cjWmxY5ihkCG12Q==",
intelKey:
"wSNX3mu+YGc/2I1DDd0NmrYHS6zS1BQt2geMUH7DDowER43JGeJRUErOHVwU2tz6xHDXia8BuvXQI3j37I0uYw==",
},
program: {
image: Program,
description:
"You can now trade YOUR data for cash! Just scan a receipt or link an account.",
terms: Terms,
learn: LearnMore,
bullets: [
{ text: "Creepy targeted ads", isUsed: false },
{ text: "Spot purchasing trends", isUsed: true },
{ text: "Create aggregate insights", isUsed: true },
],
usecases: [
Usecase.common(CommonUsecases.DISTRIBUTION),
Usecase.common(CommonUsecases.ANALYTICS),
Usecase.common(CommonUsecases.AI_TRAINING),
Usecase.common(CommonUsecases.ATTRIBUTION),
],
destinations: ["mytiki.com"],
tags: [
Tag.common(CommonTags.USER_ID),
Tag.common(CommonTags.PURCHASE_HISTORY),
],
},
theme: {
accentColor: "#783F10",
},
rewards: [
{
image: ScanReward,
description:
"Earn 10 points for every receipt you scan or in your linked accounts.",
issuer: (
event: ReceiptEvent,
details: { receipt?: Receipt; account?: ReceiptAccount },
): number | undefined => {
if (event == ReceiptEvent.SCAN) return 10;
},
},
{
image: LinkReward,
description:
"Earn 100 points for every account you link. We only check it for receipts.",
issuer: (
event: ReceiptEvent,
details: { receipt?: Receipt; account?: ReceiptAccount },
): number | undefined => {
if (event == ReceiptEvent.LINK) return 100;
else if (event == ReceiptEvent.UNLINK) return -100;
},
},
{
image: MoreReward,
description:
"Check back for special offers and more ways to earn cash for your data.",
issuer: (
event: ReceiptEvent,
details: { receipt?: Receipt; account?: ReceiptAccount },
): number | undefined => {
return undefined;
},
},
],
redeem: (total: number): number | undefined =>
total > 0 ? total : undefined,
})
.mount("#app");
Android
For IMAP email account linking, the authorization UI uses the material bottom sheet. This requires your theme parent to extend Theme.MaterialComponents.*
<resources>
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.MaterialComponents.Light.NoActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
</style>
</resources>
Initialization
To initialize just inject the TikiService
and pass in your systems unique identifier for the user. If you use emails (you shouldn't π), we recommend hashing it first.
Initialize function reference β
<script setup lang="ts">
import { inject } from "vue";
import { type TikiService } from "@mytiki/tiki-receipt-capacitor";
const tiki: TikiService | undefined = inject("Tiki");
tiki?.initialize(id).then(() => console.log("Tiki Initialized"));
</script>
We recommend initializing as early as possible in your application, you'll want to initialize the library. We scrape accounts (which can take a few seconds) and load the user's history in the background. If you initialize early, by the time the user launches the UI, all of their receipt data will be up-to-date. No worries if not, the UI will just update as data comes in.
Open UI
Add the TikiReceipt
component to your template and a boolean ref
<script setup lang="ts">
import { inject, ref } from "vue";
import { type TikiService } from "@mytiki/tiki-receipt-capacitor";
const tiki: TikiService | undefined = inject("Tiki");
tiki?.initialize(id).then(() => console.log("Tiki Initialized"));
const present = ref(false);
</script>
<template>
<tiki-receipt v-model:present="present" />
</template>
Now just set present.value = true
to open the UI.
Logout
When a user logs out of your application, you'll want to delete any in-mem history, reward balances, and cached account credentials.
import { inject, ref } from "vue";
import { type TikiService } from "@mytiki/tiki-receipt-capacitor";
const tiki: TikiService | undefined = inject("Tiki");
await tiki?.logout();
Don't worry, license records are backed up to TIKI's immutable, hosted storage for free. After the user logs back in, call .initialize
and the library will rebuild their history and reward balance for you.
Example
While this README is helpful, it's always easier to just see it in action. In /example
there is simple demo app. On launch, it generates a new random user id, with a single button called start.
Note, if you press start before the initialization is complete, a warning will hit your console logs.
- See
example/README.md
on how to build and run the example - Check out
example/src/main.ts
to view an example configuration of the library. - In
example/src/app.vue
you'll find Vue template showcasing initialization, logout, and using a button to open the pre-built UI. - In
example/src/assets/*
there are samples for program and reward images plus markdown template files for legal terms and the learn more page. Feel free to copy, use, and modify any of these assets.
More Docs and Links
@mytiki/tiki-receipt-capacitor
@mytiki/tiki-sdk-capacitor
@mytiki/tiki-sdk-capacitor
Other TIKI Links
π Website
π Console
πΎ Discord
π€ Main GitHub
Microblink
π Website
π½ BlinkReceipt - Android
π BlinkReceipt - iOS
Open Issues
You can find active issues here in GitHub under Issues. If you run into a bug or have a question, just create a new Issue or reach out to a team member on πΎ Discord.
Key open issues to take note of:
- iOS is not functional (yet) β our team is still working through a handful of critical bugs/issues. Estimated by: 8/23.
- OAuth is not yet functional (required for Outlook), optional for Gmail.
- Not every retailer account is fully tested (yet), there may still be issues with specific implementations.
- There are a handful of smaller UX-polish related bugs, such as scrolling on the history screen does not yet work. Next release scheduled for 8/25.
Contributing
- Use GitHub Issues to report any bugs you find or to request enhancements.
- If you'd like to get in touch with our team or other active contributors, pop in our πΎ Discord.
- Please use conventional commits if you intend to add code to this project.
Project Structure
/src
: The primary Service and Component src files/service
: The implementation of TikiService/components
: The implementation of TikiReceipt/assets
: The bundled UI assets (images, icons, stylesheets)
/example
: A simple example project using the plugin
Contributors β¨
Thanks goes to these wonderful people (emoji key):
This project follows the all-contributors specification. Contributions of any kind welcome!