Product metafields are not localized in the cart transform function input

When you translate a product metafield then the metafield entry data is not received by the cart transform function in the context of the current market or language. Shopify returns always the content of the primary market. While localized content is expected.

For example in our situation we have the Netherlands as the primary market and Swiss a secondary market. For Swiss we would like to receive localized metadata to manipulate the price in a different way then for the primary market. But we only receive the metafield data of the primary market.

We tested with the following query:

query Input {
  presentmentCurrencyRate
  localization {
    language {
      isoCode
    }
    country {
      isoCode
    }
    market {
      handle
      regions {
        name
      }
    }
  }
  cart {
    lines {
      quantity
      cost {
        amountPerQuantity {
          amount
        }
      }
      merchandise {
        ... on ProductVariant {
          id
          product {
            bulk: metafield(namespace: "bulk", key: "prices") {
              value
            }
          }
        }
      }
    }
  }
}

Result for the Netherlands:

{
  "presentmentCurrencyRate": "0.94505346",
  "localization": {
    "language": {
      "isoCode": "NL"
    },
    "country": {
      "isoCode": "NL"
    },
    "market": {
      "handle": "netherlands",
      "regions": [
        {
          "name": "Netherlands"
        }
      ]
    }
  },
  "cart": {
    "lines": [
      {
        "quantity": 25,
        "cost": {
          "amountPerQuantity": {
            "amount": "35.0"
          }
        },
        "merchandise": {
          "id": "gid://shopify/ProductVariant/49623544693052",
          "product": {
            "bulk": {
              "value": "10:32,50;25:30.50;50:28;75:26"
            }
          }
        }
      }
    ]
  }
}

Result for Swiss:

{
  "presentmentCurrencyRate": "0.94505346",
  "localization": {
    "language": {
      "isoCode": "DE"
    },
    "country": {
      "isoCode": "CH"
    },
    "market": {
      "handle": "switserland",
      "regions": [
        {
          "name": "Switzerland"
        }
      ]
    }
  },
  "cart": {
    "lines": [
      {
        "quantity": 25,
        "cost": {
          "amountPerQuantity": {
            "amount": "33.0"
          }
        },
        "merchandise": {
          "id": "gid://shopify/ProductVariant/49623544693052",
          "product": {
            "bulk": {
              "value": "10:32,50;25:30.50;50:28;75:26"
            }
          }
        }
      }
    ]
  }
}

Example of the translated metafield:

Expected output in this case: Swiss translation: 10:30;25:27,50;75:24

Note the i’ve read the Localization practices for Shopify Functions documentation and be aware that the amountPerQuantity is localized and that we can use presentmentCurrencyRate . But it would be nice to have the metafield data in the context of the current market/country so we can manipulate the price, product titles or messages in a unique way for each market.

It appears that the Translate & Adapt app is not reflecting updates to the Shopify function, and the query output is only displaying the data available in the product’s metafield.

As a solution, you could structure the metafield as a JSON object containing prices for each market. The input query includes the country and language in the localization field, so by matching these values with the appropriate keys in the metafield, you can retrieve the corresponding price for the specific market. This approach would allow the app to correctly fetch the localized price for the desired output.

{
  "us-en": 19.99,
  "ca-fr": 22.99,
  "uk-en": 17.99,
  "de-de": 21.50,
  "fr-fr": 20.00
}

1 Like

@AMaL
Nice solution to use a JSON structure. We also thought about this. Only thing is that our typescript cart transform function is quick reaching the 11m instructions when adding more items to the cart. So we would like to add as little logic as possible. Probably this extra logic already means we should move to Rust.
That’s why we would like the localization work by default in Shopify Functions.

Can cart and checkout validation be used to implement checks at the cart level to detect unusually large carts? If the cart exceeds a certain threshold, the checkout process can be blocked.

Notification Display: If a large cart is detected, a notification or message can be shown on the store cart page, informing the user that their cart is too large for processing or needs adjustments. It’s just a suggestion.

1 Like

@AMaL Yes we have a cart validation function for this. The threshold at this point is 50 line items. But this merchants has a lot of big b2b orders. So we prefer not to lower this threshold. That’s why I hope Shopify will fix this in the long term.

But I agree with you that we should use for now the json/cart validation solution and/or to Rust.

Thanks for the help.

You’re welcome! I’m glad I could assist. :slightly_smiling_face:

@Liam-Shopify I tag you in this one because I would like to have Shopify a closer look on metafield localisation in Shopify Functions. I think it’s still not ideal that metafields in Shopify Functions are not localised. We have for example following use case:

Use case
For one of our bigger clients we have build a custom customiser on the storefront where they can configure custom printed products. Each printed product has different options like size, hanger set, finishing, corner type, etc. That each could add additional pricing. When custom product is added to the cart we utilise line item properties to save the configuration. We don’t utilise bundles or nested cart lines because of the customers order processing. They expect that each configured product is one line item. Note that this merchant is also using markets.

With a custom build Cart Transform logic we apply the end price based on the variant id and the line item properties for different options. We use the following JSON structure on variant level to set the line item prices.

Rules:

  • Each variant is a certain size (width and height).
  • *'_’ is the base price per market. A
  • The other keys are product options (add-ons).
  • The JSON is managed by a custom app.
    _ The JSON is parsed with serde_json*. *
  • If multiple line items use the same variant we cache the parsed JSON so it would not be parsed twice.
  • We can only deploy one Cart Transform function per store.*
{
  "_": {
    "EU": 4790,
    "DE": 4790,
    "CH": 5290,
    "AT": 4790
  },
  "F2": {
    "EU": 0,
    "DE": 0,
    "CH": 0,
    "AT": 0
  },
  "F4": {
    "EU": 500,
    "DE": 500,
    "CH": 550,
    "AT": 500
  },
  "HC": {
    "EU": 300,
    "DE": 300,
    "CH": 330,
    "AT": 300
  },
  "SB": {
    "EU": 700,
    "DE": 700,
    "CH": 770,
    "AT": 700
  },
  "SN": {
    "EU": 700,
    "DE": 700,
    "CH": 770,
    "AT": 700
  },
  "SG": {
    "EU": 700,
    "DE": 700,
    "CH": 770,
    "AT": 700
  },
  "SW": {
    "EU": 700,
    "DE": 700,
    "CH": 770,
    "AT": 700
  },
  "SS": {
    "EU": 700,
    "DE": 700,
    "CH": 770,
    "AT": 700
  },
  "T09": {
    "EU": 1000,
    "DE": 1000,
    "CH": 1000,
    "AT": 1000
  },
  "T10": {
    "EU": 1000,
    "DE": 1000,
    "CH": 1000,
    "AT": 1000
  },
  "T11": {
    "EU": 1000,
    "DE": 1000,
    "CH": 1000,
    "AT": 1000
  },
  "T12": {
    "EU": 1000,
    "DE": 1000,
    "CH": 1000,
    "AT": 1000
  },
  "T13": {
    "EU": 1000,
    "DE": 1000,
    "CH": 1000,
    "AT": 1000
  },
  "T14": {
    "EU": 1000,
    "DE": 1000,
    "CH": 1000,
    "AT": 1000
  }
}

The Issue

Inside the Rust Cart Transform function we need to parse the JSON. We noticed that this is the most heaviest part of the execution of the function. This also means when we add more markets, which very common in Europe, that the JSON structure grows and possible becomes to heavy. Especially in combination with more line items in the cart.

It would be very beneficial for complex Functions to receive localised data. So we lower the amount of data send and parsed inside the Function. Improving the execution time and lowering the input size. This allows to only parsed data that is related to the customers current localisation.

Please do not tag Shopify staff, they will review and reply when they get chance.

1 Like

Another thing I tried is to use jsonValue in the input query instead of serde_json. But still this makes the function more heavy and increases the input size.