> For the complete documentation index, see [llms.txt](https://analog.groupthought.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://analog.groupthought.com/reference/alpine/currency.md).

# Currency magics

Magics for money formatting in the browser: cents to a locale-aware money string, and conversion to the presented currency.

Magics for money formatting in the browser.

| Magic                             | What it does                                                                                                          |
| --------------------------------- | --------------------------------------------------------------------------------------------------------------------- |
| `$formatCurrency(amount)`         | Formats an amount in cents as a money string via `Intl.NumberFormat`, e.g. `1999` → `$19.99`                          |
| `$formatCurrency(amount, format)` | Same, with a format object. See [Options](#options)                                                                   |
| `$convertCurrency(amount, rate?)` | Multiplies an amount by a currency rate (default `window.Shopify.currency.rate`, the rate for the presented currency) |

Amounts are in cents, matching Liquid money values for every currency. Defaults for currency and locale come from `window.theme.currency`, then `window.Shopify.currency`. Analog sets `window.theme.currency` in `head-scripts.liquid`, so the defaults match the shopper's cart currency and locale. A null or NaN amount formats as `x.xx`, and zero with `rounded: true` renders the theme's "Free" translation.

## Examples

### Formatting a live price

Use `$formatCurrency` with `x-text` where a price changes without a page load:

```html
<span x-text="$formatCurrency(price * Math.max(quantity, 1))"></span>
```

Liquid formats the server-rendered price; the magic keeps a quantity-driven total in the same format as the shopper changes the stepper.

### Rounding to whole units

Use `rounded: true` to drop the cents:

```html
<span x-text="$formatCurrency(150000, {rounded: true})"></span>
<!-- $1,500 -->
```

Leaving `rounded` unset trims a trailing `.00` but keeps real cents, matching Liquid's `money_without_trailing_zeros`. `rounded: false` always keeps the cents, matching `money`.

### Showing the currency code

Use `form: 'explicit'` to append the ISO code after the amount:

```html
<span x-text="$formatCurrency(1999, {form: 'explicit'})"></span>
<!-- $19.99 USD -->
```

### Matching the shop's Liquid money format

Use `legacyFormat` with the shop's money format string when the output must match server-rendered prices exactly:

```html
<span x-text="$formatCurrency(1999, {legacyFormat: window.theme.currency.legacyFormat})"></span>
```

`window.theme.currency.legacyFormat` contains `shop.money_format`. Without it the magic formats through `Intl.NumberFormat`, which handles separators and symbol placement per locale but can differ from a shop's custom money format.

### Converting to the presented currency

Use `$convertCurrency` for amounts that arrive in the shop's base currency:

```html
<span x-text="$formatCurrency($convertCurrency(threshold))"></span>
```

With no `rate` argument it uses `window.Shopify.currency.rate`, so the result is in the currency the shopper sees.

## Options

The second argument to `$formatCurrency`:

| Option         | What it does                                                                    |
| -------------- | ------------------------------------------------------------------------------- |
| `currency`     | ISO 4217 code (default: the cart currency from `window.theme.currency`)         |
| `locale`       | BCP 47 locale for separators and symbol placement (default: the request locale) |
| `rounded`      | `true` drops cents, `false` keeps them, unset trims a trailing `.00`            |
| `form`         | `'short'` (default) or `'explicit'`, which appends the currency code            |
| `legacyFormat` | A Liquid money format string, e.g. `${{amount}}`. Bypasses `Intl.NumberFormat`  |
