Frequently Asked Questions (FAQ)
Last updated: 2026-05-13
Common questions and answers about Filament Address Pro.
Table of Contents
- General Questions
- Installation & Setup
- Features & Functionality
- Geocoding & Maps
- Address Verification
- International Addresses
- Performance & Optimization
- Customization
- Troubleshooting
General Questions
What is Filament Address Pro?
Filament Address Pro is a premium Laravel/Filament package for managing international addresses with smart geocoding, verification, and country-aware formatting. It provides:
- Polymorphic address storage for any model
- Google Maps integration with interactive map selection
- Address verification (USPS, Google, Smarty)
- Support for 256 countries with hierarchical subdivisions
- Live address preview in international and domestic formats
What versions of Laravel and Filament are supported?
- Laravel: 11.x, 12.x, 13.x
- Filament: 4.x, 5.x
- PHP: 8.2, 8.3
Is this package free or paid?
This is a proprietary commercial package. Pricing and licensing information available at viewflex.net.
Can I use this in open-source projects?
The package license is proprietary. Contact support@viewflex.net for licensing options for open-source projects.
Installation & Setup
Do I need a Google Maps API key?
Yes, a Google Maps API key is required for:
- Geocoding (address → coordinates)
- Reverse geocoding (coordinates → address)
- Address search field with Places autocomplete
The following Google APIs must be enabled:
- Geocoding API (required)
- Maps JavaScript API (required for address search field)
- Places API (required for the map place search)
- Address Validation API (optional, for Google verification)
How do I get a Google Maps API key?
- Go to Google Cloud Console
- Create a new project or select an existing one
- Navigate to "APIs & Services" → "Library"
- Enable the required APIs listed above
- Go to "Credentials" → "Create Credentials" → "API Key"
- Add the keys to your
.envfile (the two-key setup is recommended for production):GOOGLE_MAPS_SERVER_KEY=your_key(IP-restricted: Geocoding + Static Maps + Address Validation APIs)GOOGLE_MAPS_BROWSER_KEY=your_key(domain-restricted: Maps JavaScript + Places APIs)- Or
GOOGLE_MAPS_API_KEY=your_keyas a single-key fallback
Cost: Google provides $200/month free credit. Most applications stay within this limit.
How long does data seeding take?
Seeding country data (256 countries + 17,000+ subdivisions) takes approximately 2-3 minutes. The seeder uses updateOrCreate so it's safe to run multiple times without creating duplicates.
php artisan db:seed --class="Viewflex\FilamentAddress\Database\Seeders\CountriesDomainSeeder"Can I seed data for specific countries only?
The country seeder loads all countries from the package's bundled JSON files and is not designed for partial imports; it manages read-only reference data that the package depends on.
To work with a subset of countries in your application, seed all countries and then filter at the query level:
// Show only specific countries in a select field
Country::whereIn('iso2', ['US', 'CA', 'GB', 'AU'])->get();
// Or exclude specific countries
Country::where('is_active', true)->whereNotIn('iso2', ['XX'])->get();What database tables are created?
The package creates these tables:
countries- Country master data (256 records)country_subdivisions- Hierarchical subdivisions (17,000+ records)country_address_definitions- Address format configurationscountry_groups- Regional groupings (EU, ASEAN, etc.)country_group_members- Pivot table for groupsaddresses- Polymorphic address storageaddress_api_caches- Geocoding and verification result cache (TTL-based)address_api_audit_logs- Permanent API call log for cost tracking and analytics
Features & Functionality
How do I add addresses to my models?
Add the HasAddresses trait to any model:
use Viewflex\FilamentAddress\Concerns\HasAddresses;
class Customer extends Model
{
use HasAddresses;
}This provides:
addresses()relationshipprimaryAddress()methodsetPrimaryAddress($address)method
Can I have multiple addresses per model?
Yes! Each model can have unlimited addresses. Use is_primary to mark one as the primary address.
$customer->addresses()->create([...]);
$customer->addresses()->create([...]);
$primary = $customer->primaryAddress(); // Gets the primary oneHow does the primary address system work?
Only one address per model can be marked is_primary = true. When you set a new primary address, the package automatically unsets the previous primary.
$customer->setPrimaryAddress($newAddress);
// Old primary automatically becomes is_primary = falseWhat address fields are available?
Core Fields:
country_code- ISO 2-letter country codeadministrative_area/administrative_area_id- State/provincelocality/locality_id- Citydependent_locality/dependent_locality_id- District/neighborhoodaddress_line_1- Street addressaddress_line_2- Apartment, suite, unitpostal_code- ZIP/postal code
Additional Fields:
bldg- Building namebox- PO Box numberico- In care of (c/o)
Geographic Fields:
lat,lon- Coordinates
Verification Fields:
is_verified- Booleanneeds_review- Boolean, flagged when verification finds significant differences from user inputverification_provider- Provider name (usps,google,google_places,google_geocoding,smarty,loqate)verified_at- Timestampverification_metadata- JSON metadata
Flags:
is_primary- Primary address flag
Can I add custom fields to addresses?
Yes, you can extend the address table with additional columns:
Schema::table('addresses', function (Blueprint $table) {
$table->string('address_type')->nullable(); // e.g., 'billing', 'shipping'
$table->text('delivery_instructions')->nullable();
$table->boolean('is_residential')->default(true);
});Then extend the form to include your fields (see CUSTOMIZATION_GUIDE.md).
Geocoding & Maps
What is geocoding?
Geocoding converts addresses to coordinates (latitude/longitude). Reverse geocoding converts coordinates to addresses.
How does the address search field work?
The address search field has two parts:
Places autocomplete — powered by Google's
PlaceAutocompleteElementwith automatic session tokens. Type an address to get suggestions; selecting one populates all form fields and refreshes the map preview. All keystrokes within a session are free — only the final place selection is billed ($0.017).Map preview — a static
<img>element whosesrcpoints to the package's/filament-address/map-imageproxy route. The server fetches a Google Static Maps PNG, caches it on disk for 90 days, and serves it with a 24-hour browser cache header. The Google API key is never sent to the browser.
The map image is refreshed in two situations:
- Autocomplete selection: After a place is chosen from the search box
- Blur geocoding: After the user tabs out of Address Line 1 and coordinates are resolved
No interactive map canvas (google.maps.Map) is ever created, only the Static Maps image API is used for display. This eliminates the $0.007/load Dynamic Maps charge.
Can users enter addresses manually without the map?
Yes. Manual entry is always available regardless of input mode. What happens when the user tabs out of Address Line 1 depends on the configured mode:
autocompletemode (Google browser key configured) • the address search field handles input; blur geocoding does not run on manual text entry.geocodingmode (Google server key configured, no browser key) • blur geocoding fires on Address Line 1 blur, geocoding the typed input to fill in coordinates and address components.manualmode (or no Google key) • no blur geocoding occurs. If a Google server key is configured, a successful verification will trigger a follow-up geocode call to populate coordinates from the verified address. Without a server key, coordinates remain empty.
Verification is always a separate explicit step, triggered by the Verify button.
What happens if geocoding fails?
If geocoding fails:
- The form shows a warning notification
- Coordinates remain empty (
lat,lon= null) - The address can still be saved and verified manually
Can I disable the map preview?
Yes, by setting the ADDRESS_FORM_MAP environment variable to false:
ADDRESS_FORM_MAP=falseOr in config/addresses.php:
'filament' => [
'enable_map' => false,
],When disabled, users fill address fields manually or paste a full address into the Address Line 1 field and tab away (blur geocoding still works independently of the map).
Does the package work offline?
No, the package requires an internet connection for:
- Google Maps API (geocoding, reverse geocoding, map display)
- Address verification providers (USPS, Google, etc.)
Address Verification
What verification providers are supported?
- USPS - Free, US addresses only, authoritative
- Google Address Validation - Paid, ~40 countries
- Smarty - Paid, US + 240+ countries
How do I enable address verification?
Add to your .env:
ADDRESS_VERIFICATION_ENABLED=true
ADDRESS_VERIFICATION_PROVIDER=autoThe auto provider selects the best provider based on country and provider_priority order:
- US addresses → USPS (if configured), then Smarty, then Google
- International → Smarty (240+ countries), then Google (~40 countries)
Is verification required for addresses to be saved?
No, verification is optional. Addresses save even if verification fails. The is_verified field tracks verification status.
How do I get USPS credentials?
- Register at developer.usps.com
- Create an OAuth 2.0 app
- Copy Consumer Key and Consumer Secret to
.env:
USPS_CONSUMER_KEY=your_key
USPS_CONSUMER_SECRET=your_secretCost: Free for US addresses!
How do I get Google Address Validation credentials?
- Enable "Address Validation API" in Google Cloud Console
- Use the same API key as geocoding
- Note: This API is paid (separate from the $200 free credit)
Can I programmatically verify addresses?
Yes, use the AddressVerificationService:
use Viewflex\FilamentAddress\Services\Verification\AddressVerificationService;
$result = app(AddressVerificationService::class)->verify([
'address_line_1' => '1600 Pennsylvania Ave NW',
'locality' => 'Washington',
'administrative_area' => 'DC',
'postal_code' => '20500',
'country_code' => 'US',
]);
if ($result->isSuccessful()) {
$verified = $result->getAddressLine1(); // Standardized address
}What happens when verification fails?
When verification fails:
- Address still saves with user-entered data
is_verified= false- The form shows the geocoded data as fallback
- A notification informs the user
Exception — countries with no provider coverage: If no configured provider covers the address country (e.g. China with Google-only, most of Africa with Google-only) and Google Geocoding returned a high-confidence result (ROOFTOP or RANGE_INTERPOLATED), the address is automatically marked as verified via verification_provider = 'google_geocoding'. The badge shows "✓ Verified by Google Geocoding". Low-confidence geocoding results (GEOMETRIC_CENTER, APPROXIMATE) are not promoted — they remain unverified and set needs_review = true. This fallback never fires when Smarty is configured, since Smarty covers all 240+ countries.
International Addresses
How many countries are supported?
256 countries and territories with full subdivision data (17,000+ subdivisions).
Do international addresses work differently?
Yes! The form dynamically adapts based on the selected country:
- Field labels change (e.g., "State" vs "Province" vs "Prefecture")
- Subdivision options load hierarchically (State → City → District)
- Postal code validation uses country-specific patterns
- Address formatting uses country-specific templates
What is the subdivision hierarchy?
Most countries use up to 3 levels:
- Level 1: State, Province, Prefecture, Region
- Level 2: City, Municipality, District
- Level 3: Neighborhood, Ward, Subdistrict
Example (Japan):
- Tokyo (Prefecture) → Level 1
- Minato City → Level 2
- Shibakōen → Level 3
How does the package handle Japanese addresses?
Japanese addresses have a unique format with premise numbers before street names. The package uses a specialized JapaneseAddressExtractor that:
- Parses hierarchical structure correctly
- Handles sublocality levels 1, 2, 3
- Formats addresses in the correct order
Can I add custom address formats for specific countries?
Yes, via configuration:
// config/addresses.php
'component_extraction' => [
'XX' => [ // Your country code
'address_line_1' => ['premise', 'route', 'street_number'],
'dependent_locality' => ['sublocality_level_1', 'administrative_area_level_3'],
'separator' => ' ',
],
],The package includes custom extractors for Japan, China, South Korea, and Greece, plus a default extractor that handles the remaining 250+ countries using standard Western address conventions. Config-based extraction lets you tune component mapping for any country without writing PHP.
What about countries without states/provinces?
The form automatically shows or hides fields based on each country's address definition. For countries with no subdivisions (Singapore, Monaco, Vatican City, etc.), state/province and city dropdowns are hidden automatically, no configuration required.
Performance & Optimization
Will this slow down my application?
The package is optimized for performance:
- Subdivision options load on-demand (AJAX)
- Database queries use indexes
- Optional caching for country/subdivision data
- Geocoding happens only when needed (blur events, map interaction)
How can I improve performance?
- Enable caching in
config/addresses.php:
'cache' => [
'enabled' => true,
'ttl' => 3600, // 1 hour
],Database indexes — already included in the package migration. No action needed for standard use. The migration creates indexes for all common query patterns: entity lookup, primary address, label lookup, country/subdivision, postal code, verification status, quality score, and duplicate detection. If you add custom columns and query by them, add your own indexes in a separate migration.
Eager load relationships:
$customers = Customer::with('addresses')->get();Does the package cache API responses?
Yes! The package includes comprehensive API caching:
- Geocoding cache: Enabled by default, 30-day TTL
- Verification cache: Enabled by default, 30-day TTL
- Static map image cache: Enabled by default, 90-day TTL, PNG files stored on disk at
storage/app/map-cache/ - Audit logging: Tracks all API operations including synthetic entries for autocomplete
- Cost tracking: View complete costs (geocoding + autocomplete + verification) and savings in admin panel
Note: Autocomplete costs are tracked via synthetic audit log entries when users select from map/autocomplete, providing complete cost accounting.
Configure in .env:
ADDRESS_GEOCODING_CACHE_ENABLED=true
ADDRESS_GEOCODING_CACHE_TTL_GEOCODE=2592000 # 30 days
ADDRESS_GEOCODING_CACHE_TTL_VERIFY=2592000 # 30 days
ADDRESS_STATIC_MAP_CACHE_ENABLED=true
ADDRESS_STATIC_MAP_CACHE_TTL=7776000 # 90 daysMonitoring: Admin Panel → Address API Cache & Audit Logs
For static map cache:
php artisan addresses:map-cache:stats # Count, size, oldest entry
php artisan addresses:map-cache:cleanup # Delete expired entries
php artisan addresses:map-cache:clear # Delete all (with confirmation)How many API calls does the package make?
Via address search field (Places autocomplete):
- All type-ahead keystrokes are free • session tokens make them $0
- 1 Autocomplete session billed on place selection • $0.017 (configurable via
ADDRESS_API_COST_AUTOCOMPLETE) - 1 reverse geocode call to resolve subdivisions • $0.005
Via blur geocoding (typing in address fields):
- 1 forward geocode call per blur event • $0.005
- No autocomplete charges at all
Plus (if enabled):
- 1 verification call per address (USPS is free; Google/Smarty are paid)
With caching: Repeated lookups for the same coordinates/address cost $0.
Most applications stay within Google's free tier ($200/month credit).
Cost tracking: The audit log records one entry per map selection ($0.017 - exactly one Autocomplete session). This is precise, not an approximation.
Does the package use session tokens for autocomplete?
Yes.
The address search field uses Google's PlaceAutocompleteElement, which manages session tokens automatically. All type-ahead keystrokes within a session are free; only the final place selection is billed as one session at $0.017.
| Input method | Type-ahead cost | Reverse geocode | Total per selection |
|---|---|---|---|
| Map search (any number of keystrokes) | $0.000 (free, session tokens) | $0.005 | $0.022 |
| Blur geocoding | $0 | $0.005 (forward) | $0.005 |
Cost tracking: The audit log records one entry per map selection ($0.017). Combined with the reverse geocode entry ($0.005), the full cost of each map selection is accurately captured.
What is blur geocoding and how does it work?
Blur geocoding automatically geocodes addresses when users tab out of the address field. It provides a smooth UX alternative to requiring autocomplete selection.
How it works:
- User types address in the address_line_1 field
- User presses Tab or clicks away (blur event)
- System checks if geocoding should run (via guard system)
- If approved, geocodes and fills remaining fields automatically
Configuration:
ADDRESS_BLUR_GEOCODING_ENABLED=true # Enable/disable
ADDRESS_BLUR_MIN_LENGTH=10 # Minimum charactersBenefits:
- More flexible than requiring autocomplete selection
- Supports pasted addresses
- Users can type naturally without waiting for suggestions
How can I reduce API costs for blur geocoding?
Use the power-user options to intelligently throttle API calls:
Option 1: Require Field Completeness
ADDRESS_BLUR_REQUIRE_COMPLETENESS=basic # Requires city OR postalany- No requirements (0% reduction)basic- City OR postal required (~30% reduction) ⭐ Recommendedcomplete- City AND state required (~50% reduction)
Option 2: Smart Detection
ADDRESS_BLUR_SMART_DETECTION=smart # 0.60 confidence thresholdbasic- Always geocode (0% reduction)smart- Confidence >= 0.60 (~40-55% reduction) ⭐ Recommendedaggressive- Confidence >= 0.80 (~60-80% reduction)
Recommended production setup:
ADDRESS_BLUR_REQUIRE_COMPLETENESS=basic
ADDRESS_BLUR_SMART_DETECTION=smartResult: ~50-65% API call reduction with excellent UX
See: USER-GUIDE.md - Blur Geocoding Configuration for detailed guide.
What is confidence scoring?
Confidence scoring analyzes address data quality before geocoding to prevent wasteful API calls.
Scoring factors (0.0 - 1.0 scale):
- Has street number (e.g., "123"): +0.25
- Token count >= 3 (e.g., "123 Main Street"): +0.15
- Has city: +0.20
- Has state: +0.20
- Has postal code: +0.20
- Full address detected (5+ tokens or comma): +0.10
Examples:
"123 Main Street" + city = 0.60 ✅ (passes 'smart' threshold)
"123 Main" + city = 0.45 ❌ (below threshold, skips geocoding)
"Main Street" + city + state = 0.40 ❌ (no street number)Configuration:
ADDRESS_BLUR_SMART_DETECTION=smart # 0.60 thresholdDoes blur geocoding work when a full address is entered?
Yes! When ADDRESS_BLUR_DETECT_PASTE=true, the package inspects the content of address_line_1 at blur time and applies a confidence boost if it looks like a complete address.
Detection heuristics (run at blur, not on paste event):
- Contains comma (e.g., "123 Main St, Brooklyn, NY")
- Length > 30 characters
- 5+ space-separated tokens
- Multiple components detected
Example:
User types or pastes: "1600 Pennsylvania Ave NW, Washington, DC 20500"
At blur: comma + 7 tokens detected → full-address confidence boost applied
Result: Geocoding triggered + fields populatedNote: the trigger is always the blur event (tab away / click out). Typing a full address and tabbing away produces identical behavior to pasting one.
Full-address detection gives a +0.10 confidence bonus, helping complete addresses pass smart detection thresholds.
Should I disable blur geocoding if I use the map search?
They are mutually exclusive; you don't configure both. The ADDRESS_INPUT_MODE setting determines which is active:
| Mode | How it's selected | Field population |
|---|---|---|
autocomplete | Browser API key present | PlaceAutocompleteElement (map searchbox) |
geocoding | Server key only, no browser key | Blur geocoding (tab out of Address Line 1) |
manual | No API keys | User fills all fields manually |
In autocomplete mode, blur geocoding is disabled; tabbing out of Address Line 1 does not trigger a geocode call. The map searchbox is the sole input mechanism for auto-population.
In geocoding mode, the map preview shows a static image but has no search; blur geocoding handles everything.
Set the mode explicitly in .env:
ADDRESS_INPUT_MODE=auto # Default: detects from keys (browser key → autocomplete, server only → geocoding)
ADDRESS_INPUT_MODE=autocomplete # Force autocomplete (requires browser key)
ADDRESS_INPUT_MODE=geocoding # Force geocoding (requires server key)
ADDRESS_INPUT_MODE=manual # Disable all API-driven populationHow do I monitor API usage and costs?
Built-in monitoring tools:
Address API Cache (Admin Panel)
- View cache hit ratio
- See cost savings
- Monitor cache size
Address API Audit Logs (Admin Panel)
- Track all API calls
- Filter by operation (geocode, verify)
- Filter by provider (Google, USPS, etc.)
- Export for analysis
Command-line tools:
# View cache statistics
php artisan addresses:cache:stats
# View last 7 days
php artisan addresses:cache:stats --days=7
# Clean expired cache
php artisan addresses:cache:cleanupCost calculation example:
- Geocoding: ~$0.005 per request
- USPS verification: Free (US only)
- Google verification: ~$0.005 per request
- Cache hit ratio: 65% (typical with smart detection)
- Effective cost: ~$0.00175 per address (65% savings!)
Customization
Can I customize the form appearance?
Yes! The package provides CSS hooks for all visual elements. See CUSTOMIZATION_GUIDE.md for details.
Can I add custom fields to the address form?
Yes, extend the form class:
class CustomAddressForm extends AddressForm
{
public static function schema(): array
{
$schema = parent::schema();
$schema[] = TextInput::make('delivery_notes');
return $schema;
}
}Can I change field labels?
Yes, via configuration or by extending the form. See USER-GUIDE.md for examples.
Can I use this package without Filament?
The package is designed for Filament and uses Filament form components. However, the core services (GeocodingService, CountryService, etc.) can be used standalone in any Laravel application.
Troubleshooting
"Class not found" errors after installation
php artisan optimize:clear
composer dump-autoloadGeocoding returns "API key not configured"
Check your .env file:
php artisan tinker
>>> config('addresses.google_maps_server_key') // for geocoding
>>> config('addresses.google_maps_browser_key') // for address search field / Places AutocompleteIf null, set GOOGLE_MAPS_SERVER_KEY and GOOGLE_MAPS_BROWSER_KEY in .env (or GOOGLE_MAPS_API_KEY as a single-key fallback).
Subdivisions not loading in dropdown
- Verify data is seeded:
php artisan tinker
>>> Models\CountrySubdivision::count()- If count is 0, run seeder:
php artisan db:seed --class="Viewflex\FilamentAddress\Database\Seeders\CountriesDomainSeeder"Verification always fails
Check provider configuration:
php artisan tinker
>>> config('addresses.verification')For USPS:
- Verify credentials in
.env - Ensure address is in US
- Check logs:
storage/logs/laravel.log
For Google:
- Enable "Address Validation API" in Google Cloud
- Ensure billing is enabled
- Check API key restrictions
Map image is not loading
- Check API key - Must have Maps JavaScript API and Static Maps API enabled
- Check proxy route - Visit
/filament-address/map-image?lat=40.7128&lng=-74.0060directly; a PNG should download - Check browser console - Look for 4xx/5xx errors on the proxy request
- Check storage permissions - Laravel must be able to write to
storage/app/map-cache/ - Check API restrictions - Ensure your server IP is allowed in Google Cloud credentials
- Clear browser cache - Hard refresh (Ctrl+Shift+R)
- Publish assets - Run
php artisan filament:assetsif the JS component is outdated
Address preview not updating
The preview updates reactively when form fields change. If it's not updating:
- Check browser console for JavaScript errors
- Ensure Livewire is working (
wire:keyattributes present) - Clear browser cache
- Check that country is selected (preview requires country first)
Postal code validation failing
Each country has specific postal code patterns. If validation fails:
- Check the pattern in
country_address_definitionstable - Verify the postal code matches the country's format
- Some countries have optional postal codes (field is not required)
Bulk operations run but nothing happens
Several operations dispatch Laravel background jobs. If jobs are not processing, you likely do not have a queue worker running.
Start a worker:
php artisan queue:workFor production, use a process supervisor (Supervisor, Forge, etc.) to keep the worker running. See the Laravel Queue documentation for details.
Features that require a running queue worker:
- Bulk verification — always dispatches a background job
- Import — queued when file has > 50 rows or Verify/Geocode options are enabled (small imports without API calls run synchronously)
- Recalculate Quality Scores — always dispatches a background job (the selected-records bulk action runs synchronously when the queue driver is
sync) - USPS
queuebehavior — queues requests when the hourly rate limit is hit
Sync driver: When
QUEUE_CONNECTION=sync(the default), all jobs run inline during the HTTP request — no worker needed. This is fine for development but may cause timeouts with large datasets in production.
If you do not want to manage a queue worker, change the USPS rate limit behavior:
USPS_LIMIT_BEHAVIOR=fail # Return an error when the limit is hit
USPS_LIMIT_BEHAVIOR=fallback # Fall back to Google verificationChunk processing and reliability: All background jobs process data in chunks (50 addresses for verification and import, 200 for quality scores). Each chunk is wrapped in a database transaction with automatic retry (up to 3 attempts with backoff). If a chunk still fails after retries, the job logs the error and continues to the next chunk — partial progress is preserved.
Performance issues with large datasets
If you have thousands of addresses:
- Add database indexes (see Performance section above)
- Enable caching
- Use pagination in tables
- Eager load relationships
Package updates breaking custom code
To minimize breaking changes:
- Use CSS hooks instead of publishing views
- Extend classes rather than modifying package files
- Keep customizations in your app directory
- Review CHANGELOG.md before updating
Still Need Help?
- Documentation: README.md, USER-GUIDE.md, API-REFERENCE.md
- Examples: EXAMPLES.md
- Email Support: support@viewflex.net
- Bug Reports: GitHub Issues
Built with ❤️ by Viewflex