> For the complete documentation index, see [llms.txt](https://docs.customerglu.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.customerglu.com/integration-doc/using-__glu_nudge_click-for-widget-visibility.md).

# Using \_\_GLU\_NUDGE\_CLICK for Widget Visibility

### Overview

When a CustomerGlu widget reaches its `completed` state, it stores interaction data in localStorage under the key `__GLU_NUDGE_CLICK`. By default, the widget is automatically hidden when the click count is 1 or more.

> **Important Notes:**
>
> * This data is also stored on the backend and synced across devices
> * The visibility threshold can be customized through Visibility Conditions under Widget Configuration view for a campaign

### Data Structure

The `__GLU_NUDGE_CLICK` property uses the following structure:

```json
{
  "userID": {
    "entrypointId": {
      "campaignId": {
        "clickedCount": 1
      }
    }
  }
}
```

#### Example Data

```json
{  
  "glutest-c840f891-623a-4c0e-9024-3c429575a574": {
    "66f6d8a92c87ddc90dac0fb5": {
      "2512c8d6-1233-411f-8939-83ea68e50006": {
        "clickedCount": 1
      }
    }
  }
}
```

#### Field Explanation

* `userID`: A unique identifier for the user
* `entrypointId`: The ID representing the entry point where the widget is displayed
* `campaignId`: The ID of the campaign associated with the widget
* `clickedCount`: The number of times the widget was clicked (widget is hidden when this equals or exceeds the configured threshold, default is 1)

### How to Access Widget Visibility?

#### Basic Code Example

```javascript
// Read and parse the localStorage data
function getWidgetData() {
  const keyName = "__GLU_NUDGE_CLICK";
  const storedData = localStorage.getItem(keyName);
  
  if (storedData) {
    try {
      return JSON.parse(storedData);
    } catch (error) {
      console.error("Error parsing widget data:", error);
      return null;
    }
  }
  
  return null;
}

// Check if a specific widget should be visible
function isWidgetVisible(userId, entrypointId, campaignId) {
  const data = getWidgetData();
  
  if (!data) {
    // No data means the widget hasn't been clicked yet
    return true;
  }
  
  // Navigate through the nested structure to get clickCount
  // Using optional chaining for safety
  const clickCount = data[userId]?.[entrypointId]?.[campaignId]?.clickedCount || 0;
  
  // Widget is hidden when clickCount is 1 or more (default configuration)
  // Note: This threshold may be different if configured in the CustomerGlu dashboard
  return clickCount < 1;
}
```

### Use Cases

#### 1. Conditional UI Rendering

```javascript
function updateUI() {
  const userId = "user-123"; // Your actual user ID
  const entrypointId = "entry-456"; // Your entrypoint ID
  const campaignId = "campaign-789"; // Your campaign ID
  
  if (isWidgetVisible(userId, entrypointId, campaignId)) {
    // Show related UI elements
    document.getElementById("related-element").style.display = "block";
  } else {
    // Hide related UI elements or show alternatives
    document.getElementById("related-element").style.display = "none";
    document.getElementById("alternative-element").style.display = "block";
  }
}
```

#### 2. Listening for Visibility Changes

```javascript
function setupVisibilityListener(userId, entrypointId, campaignId, callback) {
  // Initial check
  callback(isWidgetVisible(userId, entrypointId, campaignId));
  
  // Listen for localStorage changes
  window.addEventListener("storage", (event) => {
    if (event.key === "__GLU_NUDGE_CLICK") {
      callback(isWidgetVisible(userId, entrypointId, campaignId));
    }
  });
}

// Usage
setupVisibilityListener("user-123", "entry-456", "campaign-789", (isVisible) => {
  console.log("Widget is now:", isVisible ? "visible" : "hidden");
  updateUI();
});
```

#### 3. Integration with Segment API

This example shows how to combine widget visibility with the Segmentation API:

```javascript
async function handleWidgetCompletion(userId, campaignId) {
  // Check if widget is hidden (completed)
  const isVisible = isWidgetVisible(userId, entrypointId, campaignId);
  
  if (!isVisible) {
    // Widget is completed, move user to next campaign
    try {
      // Remove from current campaign
      await fetch(`https://api-us.customerglu.com/segment/${campaignId}/user/delete`, {
        method: 'DELETE',
        headers: {
          'Content-Type': 'application/json',
          'X-API-KEY': 'your-api-key'
        },
        body: JSON.stringify({ userId })
      });
      
      // Add to next campaign
      await fetch(`https://api-us.customerglu.com/segment/next-campaign-id/user/add`, {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          'X-API-KEY': 'your-api-key'
        },
        body: JSON.stringify({ userId })
      });
      
    } catch (error) {
      console.error("Error updating user segments:", error);
    }
  }
}
```

### Best Practices

#### 1. Defensive Coding

Always implement error handling when accessing localStorage:

```javascript
javascriptCopyfunction getClickCount(userId, entrypointId, campaignId) {
  try {
    const data = getWidgetData();
    return data?.[userId]?.[entrypointId]?.[campaignId]?.clickedCount || 0;
  } catch (error) {
    console.error("Error getting click count:", error);
    return 0; // Default on error
  }
}
```

#### 2. Performance Considerations

* Avoid checking localStorage in tight loops or high-frequency events
* Consider caching the result if checking frequently:

```javascript
javascriptCopy// Cache visibility state with a simple refresh mechanism
const visibilityCache = {
  data: {},
  timestamp: 0,
  ttl: 5000, // 5 seconds cache validity
  
  getVisibility(userId, entrypointId, campaignId) {
    const key = `${userId}:${entrypointId}:${campaignId}`;
    const now = Date.now();
    
    // Refresh cache if expired
    if (now - this.timestamp > this.ttl) {
      this.data = {};
      this.timestamp = now;
    }
    
    // Return cached value if exists
    if (this.data[key] !== undefined) {
      return this.data[key];
    }
    
    // Calculate and cache new value
    const isVisible = isWidgetVisible(userId, entrypointId, campaignId);
    this.data[key] = isVisible;
    return isVisible;
  }
};
```

#### 3. Cross-Device Considerations

Since the widget state is synced across devices via the backend, users will generally see consistent widget visibility across their devices. However, there might be a short delay in synchronization.

### Troubleshooting

#### Widget Visibility Inconsistencies

If the widget visibility state seems inconsistent:

1. Verify you're using the correct IDs (userId, entrypointId, campaignId)
2. Check the raw localStorage data:

   ```javascript
   javascriptCopyconsole.log(JSON.parse(localStorage.getItem("__GLU_NUDGE_CLICK")));
   ```
3. Check if the visibility conditions have been customized in the CustomerGlu dashboard
4. Verify there are no network issues preventing backend sync

#### Missing Data

If no data appears in localStorage:

1. Confirm the user has interacted with at least one widget
2. Check browser localStorage permissions and quotas
3. Verify the CustomerGlu SDK is properly initialized

### Visibility Configuration

The default behavior is to hide widgets when clickCount is 1 or more, but this can be customized:

1. Navigate to the Campaign in CustomerGlu dashboard
2. Select the Widget Configuration view
3. Find and update the Visibility Conditions according to your needs
