# Contact Local Weather

{% @arcade/embed flowId="NJM1wTw0EGS66VVNCAjF" url="<https://app.arcade.software/share/NJM1wTw0EGS66VVNCAjF>" %}

{% hint style="danger" %}
This use case has some configuration prerequisites. Make sure you review the **Set up** section of this page before buildin !
{% endhint %}

{% hint style="success" %}

#### **Learning focus points**

* Display **external data** in Avonni **Dynamic Components**
* Use **HTTP callout actions** in flow
* Populate components using **on-load interactions** and flows
  {% endhint %}

***

## Objective <a href="#id-5f56e1d2-78d8-4f63-af33-0db54f71471a" id="id-5f56e1d2-78d8-4f63-af33-0db54f71471a"></a>

* Build a dynamic card on contacts that return the locale weather data on page load
* Push the boundaries of your customer 360 knowledge

***

## Solution <a href="#a25298b6-ce1d-426e-8db8-aa41f1cf4fca" id="a25298b6-ce1d-426e-8db8-aa41f1cf4fca"></a>

This solution uses **Avonni Dynamic Components** combined with **Salesforce flow** and **HTTP callout action**, all built with **no code**.

Users get a clean and colourful contact card displaying weather and key data.

### How It Works (User Perspective) <a href="#c75990c5-3e25-41fc-89d6-31e1dcfed9ca" id="c75990c5-3e25-41fc-89d6-31e1dcfed9ca"></a>

1. The user opens the contact record page
2. The component instantly loads the contact's locale weather data
3. Dynamic visibility rules ensure the component's appearance reflects the weather, just like a weather app would

<table data-view="cards"><thead><tr><th></th><th data-hidden data-card-cover data-type="image">Cover image</th></tr></thead><tbody><tr><td>Beautiful weather</td><td data-object-fit="contain"><a href="/files/2K0VN0OJI6e3yC47cLTl">/files/2K0VN0OJI6e3yC47cLTl</a></td></tr><tr><td>Nighttime</td><td><a href="/files/v08a3pwAk7rEBn7H3cXB">/files/v08a3pwAk7rEBn7H3cXB</a></td></tr><tr><td>Strong wind</td><td><a href="/files/PwkOTc5geZUsM3nyGxxc">/files/PwkOTc5geZUsM3nyGxxc</a></td></tr><tr><td>Storm</td><td><a href="/files/Rx0bAlpdpys4sZqGRtuv">/files/Rx0bAlpdpys4sZqGRtuv</a></td></tr></tbody></table>

### What we'll create <a href="#id-228f54ff-be7f-4ab7-a30a-3582c52d5dfa" id="id-228f54ff-be7f-4ab7-a30a-3582c52d5dfa"></a>

* 1 **External service** (prerequisite, completely standard configuration)
* 1 **autolaunched Flow** with an **HTTP action** to get the weather API data
* 1 **Dynamic component**
  * With an on-load interaction to ensure the component has all the relevant data upon loading

***

## Set up <a href="#f1104ea9-b30d-4396-b858-55c41b4cffd1" id="f1104ea9-b30d-4396-b858-55c41b4cffd1"></a>

### Prerequisite: Configure an external service <a href="#id-95698e6d-33c3-40d4-87c5-cf048c4f246d" id="id-95698e6d-33c3-40d4-87c5-cf048c4f246d"></a>

This use case will leverage the OpenWeather app : <https://openweathermap.org/api>

* **External Credential** = “how do I authenticate?”
* **Named Credential** = “where am I calling?”
* **Flow** = “what endpoint + parameters?”

#### Configuration

* External credential&#x20;
  * Label / Name : `OpenMeteo_NoAuth`
  * Protocol = `Custom`
    * “Custom” is what Salesforce uses for **no-auth / manual headers** cases.
* Principal
  * Parameter Name = `NoAuth`
  * Identity = `Named Principal`&#x20;
* Named Credential
  * Label / Name = `OpenMeteo`
  * URL = <https://api.open-meteo.com>
  * External Credential = `OpenMeteo_NoAuth`
* Create a Permission set named `PS_OpenMeteoAccess` to give users access
  * With External Credential Principal Access to the `OpenMeteo_NoAuth` service

### **Build the Autolaunched Flow**

{% @arcade/embed flowId="lMLeLuAaPE7IbhlnzZ1d" url="<https://app.arcade.software/share/lMLeLuAaPE7IbhlnzZ1d>" %}

{% stepper %}
{% step %}

#### In Flow Builder, create an Autolaunched Flow

{% endstep %}

{% step %}

#### Retrieve the Contact record

* Use a Get record element to get the current contact information
  * You only need the **MailingLatitude** and **MailingLongitude** for this use case
    {% endstep %}

{% step %}

#### Create the GetOpenWeather HTTP Action

* Set up an HTTP flow action with the following settings

| Parameter | Type in Flow | Example                | Dynamic | Value                                                                                                                                                           | Description                                                                                                                                                                           |
| --------- | ------------ | ---------------------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| latitude  | Double       | 45.5017                | Yes     | `Contact.MailingLatitude`                                                                                                                                       | Current contact's latitude                                                                                                                                                            |
| longitude | Double       | -73.5673               | Yes     | `Contact.MailingLongitude`                                                                                                                                      | Current contact's longitude                                                                                                                                                           |
| current   | String       | comma-separated fields | Static  | `temperature_2m,apparent_temperature,weather_code,wind_speed_10m,precipitation,rain,showers,is_day`                                                             | <p>All current weather (now) fields the HTTP request will return. Use those needed for your use case.<br><br>Output will be a variable of the weather at the time of the request.</p> |
| daily     | String       | comma-separated fields | Static  | `temperature_2m_max,temperature_2m_min,precipitation_probability_max,rain_sum,showers_sum,precipitation_sum,sunrise,sunset,daylight_duration,sunshine_duration` | <p>All daily weather fields the HTTP request will return. Use those needed for your use case.<br><br>Output will be a collection of the next 7 days' weather data.</p>                |
| timezone  | String       | auto                   | Static  | `auto`                                                                                                                                                          | Timezone of the locale.                                                                                                                                                               |

* Return JSON example

{% code expandable="true" %}

```json
{
"utcx5foffsetx5fseconds_set": true,
"utcx5foffsetx5fseconds": -14400,
"timezonex5fabbreviation_set": true,
"timezonex5fabbreviation": "GMT-4",
"timezone_set": true,
"timezone": "America/New_York",
"longitude_set": true,
"longitude": -73.975105,
"latitude_set": true,
"latitude": 40.762505,
"generationtimex5fms_set": true,
"generationtimex5fms": 0.41556358337402344,
"elevation_set": true,
"elevation": 16,
"dailyx5funits_set": true,
"dailyx5funits": {
"z0time_set": true,
"z0time": "iso8601",
"temperaturex5f2mx5fmin_set": true,
"temperaturex5f2mx5fmin": "°C",
"temperaturex5f2mx5fmax_set": true,
"temperaturex5f2mx5fmax": "°C",
"sunshinex5fduration_set": true,
"sunshinex5fduration": "s",
"sunset_set": true,
"sunset": "iso8601",
"sunrise_set": true,
"sunrise": "iso8601",
"showersx5fsum_set": true,
"showersx5fsum": "mm",
"rainx5fsum_set": true,
"rainx5fsum": "mm",
"precipitationx5fsum_set": true,
"precipitationx5fsum": "mm",
"precipitationx5fprobabilityx5fmax_set": true,
"precipitationx5fprobabilityx5fmax": "%",
"daylightx5fduration_set": true,
"daylightx5fduration": "s"
},
"daily_set": true,
"daily": {
"z0time_set": true,
"z0time": [
"2026-03-26",
"2026-03-27",
"2026-03-28",
"2026-03-29",
"2026-03-30",
"2026-03-31",
"2026-04-01"
],
"temperaturex5f2mx5fmin_set": true,
"temperaturex5f2mx5fmin": [
6.7,
4.3,
-0.3,
1.9,
6.3,
8.7,
8
],
"temperaturex5f2mx5fmax_set": true,
"temperaturex5f2mx5fmax": [
24.5,
16.2,
5.8,
10.6,
14.2,
13.1,
24.8
],
"sunshinex5fduration_set": true,
"sunshinex5fduration": [
31462.92,
0,
43211.37,
43200,
22562.3,
21378.7,
41607.48
],
"sunset_set": true,
"sunset": [
"2026-03-26T19:14",
"2026-03-27T19:15",
"2026-03-28T19:16",
"2026-03-29T19:17",
"2026-03-30T19:18",
"2026-03-31T19:19",
"2026-04-01T19:20"
],
"sunrise_set": true,
"sunrise": [
"2026-03-26T06:48",
"2026-03-27T06:47",
"2026-03-28T06:45",
"2026-03-29T06:43",
"2026-03-30T06:42",
"2026-03-31T06:40",
"2026-04-01T06:38"
],
"showersx5fsum_set": true,
"showersx5fsum": [
0,
0,
0,
0,
0,
0,
0
],
"rainx5fsum_set": true,
"rainx5fsum": [
1.4,
11.22,
0,
0,
4,
6,
0.3
],
"precipitationx5fsum_set": true,
"precipitationx5fsum": [
1.4,
11.22,
0,
0,
4,
6,
0.3
],
"precipitationx5fprobabilityx5fmax_set": true,
"precipitationx5fprobabilityx5fmax": [
35,
60,
21,
1,
17,
30,
34
],
"daylightx5fduration_set": true,
"daylightx5fduration": [
44711.08,
44873.78,
45036.72,
45199.8,
45362.93,
45526.01,
45688.93
]
},
"currentx5funits_set": true,
"currentx5funits": {
"z0time_set": true,
"z0time": "iso8601",
"windx5fspeedx5f10m_set": true,
"windx5fspeedx5f10m": "km/h",
"weatherx5fcode_set": true,
"weatherx5fcode": "wmo code",
"temperaturex5f2m_set": true,
"temperaturex5f2m": "°C",
"showers_set": true,
"showers": "mm",
"rain_set": true,
"rain": "mm",
"precipitation_set": true,
"precipitation": "mm",
"isx5fday_set": true,
"isx5fday": "",
"interval_set": true,
"interval": "seconds",
"apparentx5ftemperature_set": true,
"apparentx5ftemperature": "°C"
},
"current_set": true,
"current": {
"z0time_set": true,
"z0time": "2026-03-26T08:45",
"windx5fspeedx5f10m_set": true,
"windx5fspeedx5f10m": 15,
"weatherx5fcode_set": true,
"weatherx5fcode": 3,
"temperaturex5f2m_set": true,
"temperaturex5f2m": 10.5,
"showers_set": true,
"showers": 0,
"rain_set": true,
"rain": 0,
"precipitation_set": true,
"precipitation": 0,
"isx5fday_set": true,
"isx5fday": 1,
"interval_set": true,
"interval": 900,
"apparentx5ftemperature_set": true,
"apparentx5ftemperature": 7.4
}
}
```

{% endcode %}

{% hint style="info" %}
This configuration provides you with extra data for full flexibility in your implementation.&#x20;

We will not be using everything for this example : the `daily` configuration is optional.

View the [#going-further](#going-further "mention")section for expanded ideas on this use case.
{% endhint %}
{% endstep %}

{% step %}

#### Assign variables for output

* Use an assignment to map output variables that you want to display in the dynamic component
* Create and assign output variables and formulas
* Assign the action's outputs to variables for easier data management and to transfer them to the dynamic component
* Use formulas to create useful booleans

{% hint style="danger" %}
Review the [#flow-variables](#flow-variables "mention") table for details.
{% endhint %}
{% endstep %}

{% step %}

#### Save and test your flow

{% endstep %}
{% endstepper %}

#### **Flow variables**

| Variable name     | Type    | Description                                                      |
| ----------------- | ------- | ---------------------------------------------------------------- |
| vCurrentTemp      | Number  | Current temperature                                              |
| vCurFeelsLike     | Number  | Current "feels like" temperature                                 |
| vCurPrecipitation | Number  | Current amount of precipitation (mm)                             |
| vCurWindSpeed     | Number  | Current wind speed (km/h)                                        |
| vCurStrongWind    | Boolean | True if the wind is over a speed threshold (defined in the flow) |
| vOutCurIsDay      | Boolean | True if the API returns that it is currently daytime             |

**Formulas**

| Name             | Type    | Formula                                   | Description |
| ---------------- | ------- | ----------------------------------------- | ----------- |
| F\_CurStrongWind | Boolean | IF ( {!vCurWindSpeed} > 50 , true, false) |             |
| F\_IsDay         | Boolean | IF ( {!vCurIsDay} = 1, true, false)       |             |

***

## Build the Dynamic Component

{% @arcade/embed flowId="dchXQ7XDTYoy90VOcboK" url="<https://app.arcade.software/share/dchXQ7XDTYoy90VOcboK>" %}

*This arcade only goes through the On-load interaction, an image and visibility rules. View bellow fort he full setup.*

{% stepper %}
{% step %}

#### Create variables

* Create **input** variables to retrieve data from the flow (names are those used in the example)
* Variables should match the flow outputs

{% hint style="danger" %}
Review the [#component-variables](#component-variables "mention") table for details.
{% endhint %}
{% endstep %}

{% step %}

#### Create an On-Load interaction

* In the left panel, create a on-load interaction&#x20;
  * **Type** : Execute flow
  * **Flow Name** : select your autolaunched flow
  * **Input** : recordId
  * **Output** : map all the input variables created in step 1 witht the flow output variables
    {% endstep %}

{% step %}

#### Set up Dynamic styling

* Add a Container component
* Make the background colourful and dynamic&#x20;
  * In the Style tab, set the background colour to the `F_BackgroundColour` variable
    {% endstep %}

{% step %}

#### Configure the Header

* Add a container in the first slot
  * In the style tab, set background to `#cfe9fe` (or your colour of choice)
* Add a Media Object in the container to organize items
* Add an Avatar, fields, chip container (tags) and buttons to customize the header

{% hint style="info" %}
We won't go into details as these components are examples and not critical to the use case.&#x20;

Navigate to the [#going-further](#going-further "mention")section for guidance about configuration.
{% endhint %}
{% endstep %}

{% step %}

#### Build the image column

* Drag a column component into the canvas and divide it into 2 columns
* Use the left column to display weather images dynamically, this column will display the main weather image
  * Drag image components and set visibility rules (use your choice of images as **Image Source**).&#x20;
    * "Sun / Daylight"
      * Set Visibility rule = `F_MainWeatherIcon` = `Sun`
    * "Night"
      * Set Visibility rule = `F_MainWeatherIcon` = `Moon`
    * "Rain"
      * Set Visibility rule = `F_MainWeatherIcon` = `Rain`
    * "Storm"
      * Set Visibility rule = `F_MainWeatherIcon` = `Storm`
    * "Wind"
      * Set Visibility rule = `F_MainWeatherIcon` = `Wind`&#x20;
        {% endstep %}

{% step %}

#### Configure the widget column

* Populate the right column of the component with your widgets
* Use Text components, containers and images to build widgets showcasing important data, such as the temperature, precipitation and wind speed

{% endstep %}

{% step %}

#### Save and review

{% endstep %}
{% endstepper %}

#### **Dynamic Component Variables**

| vCurrentTemp      | Number  | Current temperature                                              |
| ----------------- | ------- | ---------------------------------------------------------------- |
| vCurFeelsLike     | Number  | Current "feels like" temperature                                 |
| vCurPrecipitation | Number  | Current amount of precipitation (mm)                             |
| vCurWindSpeed     | Number  | Current wind speed (km/h)                                        |
| vCurStrongWind    | Boolean | True if the wind is over a speed threshold (defined in the flow) |
| vOutCurIsDay      | Boolean | True if the API returns that it is currently daytime             |

**Formulas**

<table data-header-hidden><thead><tr><th>Name</th><th>Type</th><th>Formula</th><th>Description</th></tr></thead><tbody><tr><td>F_BackgroundColour</td><td>Text</td><td><code>IF ( {!vOutCurIsDay} = true , '#1ab9ff' , '#107cad')</code></td><td>Dynamically change the background based on the vOutCurIsDay variable</td></tr><tr><td>F_TextColour</td><td>Text</td><td><code>IF ( {!vOutCurIsDay} = true , '#ffffff', '#1ab9ff')</code></td><td>Dynamically change the text colour to ensure it is readable with the background</td></tr><tr><td>F_MainWeatherIcon</td><td>Text</td><td><pre><code>IF(
OR(
{!vCurPrecipitation} >= 10,
{!vCurWindSpeed} >= 40
), "Storm",
IF(
{!vCurPrecipitation} > 0,"Rain",
IF(
  {!vCurWindSpeed} >= 20,  "Wind",
  IF(
    {!vOutCurIsDay} = true,"Sun","Moon" ))))
</code></pre></td><td>Used for your weather image visibility rules and be based on the variables created in 1</td></tr></tbody></table>

***

## Going further

#### **Ideas**

* Leverage the daily data returned by the HTTP action you've set up to build a 7 days forecast.

#### **Features**

{% content-ref url="/spaces/ODPvvv7Cx9Z9RECLn3oV/pages/1GrGlrzcpSAxkoT6ak1u" %}
[On Load Interaction](/dynamic-components/component-builder/on-load-interaction.md)
{% endcontent-ref %}

#### **Dynamic components**&#x20;

{% content-ref url="/spaces/ODPvvv7Cx9Z9RECLn3oV/pages/GApCB1OU3DCtVtOdGLx7" %}
[Avatar](/dynamic-components/components/avatar.md)
{% endcontent-ref %}

{% content-ref url="/spaces/ODPvvv7Cx9Z9RECLn3oV/pages/A2Ve6KlxDcSO42vXRl5x" %}
[Button](/dynamic-components/components/button.md)
{% endcontent-ref %}

{% content-ref url="/spaces/ODPvvv7Cx9Z9RECLn3oV/pages/yzqlAwz1bx8bb26Pu39o" %}
[Chip Container](/dynamic-components/components/chip-container.md)
{% endcontent-ref %}

{% content-ref url="/spaces/ODPvvv7Cx9Z9RECLn3oV/pages/3Ab0idmjF5E6w1ISwttH" %}
[Image](/dynamic-components/components/image.md)
{% endcontent-ref %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.avonnicomponents.com/projects/use-cases/contact-local-weather.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
