Shipeasy
ReferenceGo

Snippets

Minimal copy-paste blocks for flags, configs, kill switches, experiments and i18n.

Minimal copy-paste blocks, grouped by the registry taxonomy. These are the same leaves the docs get op returns.

release

release / flags

Read the {{FLAG_KEY}} gate for the bound user. Assumes Configure() ran at startup — see Installation.

Read a flag

// construct once per callsite (cheap; binds the user)
c := shipeasy.NewClient(shipeasy.User{"user_id": "u_123"})

// GetFlag(name) — name is the gate key; returns false if the gate is
// absent, disabled, or killswitched (never a user argument — it's bound).
if c.GetFlag("{{FLAG_KEY}}") {
    // new behaviour
}

Flag with an explicit fallback

// construct once per callsite (cheap; binds the user)
c := shipeasy.NewClient(shipeasy.User{"user_id": "u_123"})

// GetFlagOr(name, def) — def is returned ONLY when the flag can't be
// evaluated (engine not ready, or the gate is absent); a gate that
// evaluates false returns false.
on := c.GetFlagOr("{{FLAG_KEY}}", true) // name; def returned only on can't-evaluate
_ = on

release / configs

Read the {{CONFIG_KEY}} dynamic config (typed JSON value). Assumes Configure() ran at startup — see Installation.

Read a config

// construct once per callsite (cheap; binds the user)
c := shipeasy.NewClient(shipeasy.User{"user_id": "u_123"})

// GetConfig(name) — name is the config key; returns (value any, ok bool).
// ok is false when the key is absent. Type-assert value to what you stored.
if cfg, ok := c.GetConfig("{{CONFIG_KEY}}"); ok {
    m := cfg.(map[string]any) // configs are arbitrary JSON
    _ = m["cta"]
}

Config with an explicit fallback

// construct once per callsite (cheap; binds the user)
c := shipeasy.NewClient(shipeasy.User{"user_id": "u_123"})

// GetConfigOr(name, def) — def is returned when the key is absent.
v := c.GetConfigOr("{{CONFIG_KEY}}", map[string]any{"cta": "Buy"}) // name; def
_ = v

release / killswitches

Check whether the {{KILLSWITCH_KEY}} kill switch is engaged. Assumes Configure() ran at startup — see Installation.

Read a kill switch

// construct once per callsite (cheap; binds the user)
c := shipeasy.NewClient(shipeasy.User{"user_id": "u_123"})

// GetKillswitch(name) — name is the kill-switch key; true means engaged
// (the feature is killed). Returns false if the switch is absent.
if c.GetKillswitch("{{KILLSWITCH_KEY}}") {
    // feature is killed — short-circuit
}

Read a named per-key switch

// construct once per callsite (cheap; binds the user)
c := shipeasy.NewClient(shipeasy.User{"user_id": "u_123"})

// GetKillswitch(name, switchKey) — the optional switchKey selects a named
// per-key override (the dashboard "switches" feature). When that key has no
// override, it falls back to the kill switch's top-level value.
if c.GetKillswitch("{{KILLSWITCH_KEY}}", "eu") {
    // killed for the "eu" variant
}

release / experiments

Evaluate the {{EXPERIMENT_KEY}} experiment and track the {{SUCCESS_EVENT}} conversion. Assumes Configure() ran at startup — see Installation.

Evaluate and render the assigned group

// construct once per callsite (cheap; binds the user)
c := shipeasy.NewClient(shipeasy.User{"user_id": "u_123"})

// GetExperiment(name, defaultParams) — name is the experiment key;
// defaultParams is returned as r.Params when the user isn't enrolled.
r := c.GetExperiment("{{EXPERIMENT_KEY}}", map[string]any{"color": "blue"})
if r.InExperiment {
    p := r.Params.(map[string]any)
    render(p["color"])
}

Track the conversion

// construct once per callsite (cheap; binds the user)
c := shipeasy.NewClient(shipeasy.User{"user_id": "u_123"})

// Track(event, props) — Client-only; the unit id is derived from the bound
// attributes (user_id, else anonymous_id). event is the metric event name;
// props are optional numeric/string fields. Fire-and-forget.
c.Track("{{SUCCESS_EVENT}}", map[string]any{"amount": 49}) // event; props

metrics

metrics / track

Track a metric/conversion event from the bound Client. Metrics in the dashboard are computed from these events. Assumes Configure() ran at startup — see Installation.

Track an event

// construct once per callsite (cheap; binds the user)
c := shipeasy.NewClient(shipeasy.User{"user_id": "u_123"})

// Track(event, props)
//   event — the event your metric is built on (required)
//   props — optional payload; numeric/string fields you can sum/filter on in a
//           metric (private attributes are stripped before egress)
c.Track("{{EVENT_NAME}}", map[string]any{"amount": 49, "currency": "usd"})

Fire-and-forget (never blocks your response) and a no-op under ConfigureForTesting / ConfigureForOffline. The unit is the bound user (user_id, else anonymous_id); with no unit the call is a no-op.

Track without properties

// construct once per callsite (cheap; binds the user)
c := shipeasy.NewClient(shipeasy.User{"user_id": "u_123"})

c.Track("{{EVENT_NAME}}", nil) // props are optional — pass nil

i18n

i18n / setup

The Go SDK is server-side: it emits the browser i18n loader tag (public client key) for the {{PROFILE}} profile. Translation rendering itself happens in the browser via the client SDK's t(). Assumes Configure() ran at startup — see Installation.

// I18nScriptTag is package-level — it runs off the global Configure(). Emit
// the returned tag in your document <head>.
//   clientKey      string   the PUBLIC client key (NOT the server key)
//   "{{PROFILE}}"  string   the locale profile to load (e.g. "en:prod")
//   BootstrapTagOptions{}   optional: AnonID, I18nProfile, BaseURL
tag := shipeasy.I18nScriptTag(clientKey, "{{PROFILE}}", shipeasy.BootstrapTagOptions{})
_ = tag

i18n / render

There is no server-side t() in Go — translated labels are rendered in the browser by the client SDK once I18nScriptTag has loaded the {{PROFILE}} profile.

// Browser (client SDK), after the loader installs the {{PROFILE}} labels:
const label = shipeasy.t("checkout.cta");

ops

ops / see

Report a caught, handled error (or a non-exception "violation") to Shipeasy with See() — fire-and-forget, never panics into the request path. Package-level, so it reports against the configuration from Configure. Assumes Configure() ran at startup — see Installation.

Report a handled error

if err := charge(order); err != nil {
    // CausesThe(subject) — what the error affects (e.g. "checkout")
    // To(outcome)        — the terminal: what you do about it; builds + fires once
    shipeasy.See(err).CausesThe("checkout").To("use the backup processor")
    fallbackCharge(order)
}

Attach context with .Extras(...)

if err := charge(order); err != nil {
    // Extras(map) — structured fields attached to the report (sanitized:
    // string/number/bool only; private attributes stripped before egress).
    shipeasy.See(err).
        CausesThe("checkout").
        Extras(map[string]any{"order_id": order.ID}).
        To("use cached prices")
}

Report a non-exception violation

// A bad state that isn't an error — the name is a STABLE fingerprint; put
// variable data in .Extras, never the name. .To() is the terminal.
shipeasy.SeeViolation("missing_invoice").
    CausesThe("billing").
    To("skip the dunning email")

Mark an expected error — report NOTHING

if errors.Is(err, sql.ErrNoRows) {
    // transmits nothing; .Because(...) / .Extras() are local-debug only
    shipeasy.ControlFlowException(err).Because("a missing row is the empty-state path")
}
Was this page helpful?
✎ Edit this page

On this page